LLVM 22.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
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/MapVector.h"
21#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/SetVector.h"
26#include "llvm/ADT/Statistic.h"
39#include "llvm/IR/Argument.h"
40#include "llvm/IR/Assumptions.h"
41#include "llvm/IR/Attributes.h"
42#include "llvm/IR/BasicBlock.h"
43#include "llvm/IR/Constant.h"
44#include "llvm/IR/Constants.h"
45#include "llvm/IR/DataLayout.h"
47#include "llvm/IR/GlobalValue.h"
48#include "llvm/IR/IRBuilder.h"
49#include "llvm/IR/InlineAsm.h"
50#include "llvm/IR/InstrTypes.h"
51#include "llvm/IR/Instruction.h"
54#include "llvm/IR/IntrinsicsAMDGPU.h"
55#include "llvm/IR/IntrinsicsNVPTX.h"
56#include "llvm/IR/LLVMContext.h"
57#include "llvm/IR/MDBuilder.h"
58#include "llvm/IR/NoFolder.h"
59#include "llvm/IR/Value.h"
60#include "llvm/IR/ValueHandle.h"
75#include <cassert>
76#include <numeric>
77#include <optional>
78#include <string>
79
80using namespace llvm;
81
82#define DEBUG_TYPE "attributor"
83
85 "attributor-manifest-internal", cl::Hidden,
86 cl::desc("Manifest Attributor internal string attributes."),
87 cl::init(false));
88
89static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
91
92template <>
94
96
98 "attributor-max-potential-values", cl::Hidden,
99 cl::desc("Maximum number of potential values to be "
100 "tracked for each position."),
102 cl::init(7));
103
105 "attributor-max-potential-values-iterations", cl::Hidden,
106 cl::desc(
107 "Maximum number of iterations we keep dismantling potential values."),
108 cl::init(64));
109
110STATISTIC(NumAAs, "Number of abstract attributes created");
111STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");
112
113// Some helper macros to deal with statistics tracking.
114//
115// Usage:
116// For simple IR attribute tracking overload trackStatistics in the abstract
117// attribute and choose the right STATS_DECLTRACK_********* macro,
118// e.g.,:
119// void trackStatistics() const override {
120// STATS_DECLTRACK_ARG_ATTR(returned)
121// }
122// If there is a single "increment" side one can use the macro
123// STATS_DECLTRACK with a custom message. If there are multiple increment
124// sides, STATS_DECL and STATS_TRACK can also be used separately.
125//
126#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
127 ("Number of " #TYPE " marked '" #NAME "'")
128#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
129#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
130#define STATS_DECL(NAME, TYPE, MSG) \
131 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
132#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
133#define STATS_DECLTRACK(NAME, TYPE, MSG) \
134 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
135#define STATS_DECLTRACK_ARG_ATTR(NAME) \
136 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
137#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
138 STATS_DECLTRACK(NAME, CSArguments, \
139 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
140#define STATS_DECLTRACK_FN_ATTR(NAME) \
141 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
142#define STATS_DECLTRACK_CS_ATTR(NAME) \
143 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
144#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
145 STATS_DECLTRACK(NAME, FunctionReturn, \
146 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
147#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
148 STATS_DECLTRACK(NAME, CSReturn, \
149 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
150#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
151 STATS_DECLTRACK(NAME, Floating, \
152 ("Number of floating values known to be '" #NAME "'"))
153
154// Specialization of the operator<< for abstract attributes subclasses. This
155// disambiguates situations where multiple operators are applicable.
156namespace llvm {
157#define PIPE_OPERATOR(CLASS) \
158 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
159 return OS << static_cast<const AbstractAttribute &>(AA); \
160 }
161
201
202#undef PIPE_OPERATOR
203
204template <>
206 const DerefState &R) {
207 ChangeStatus CS0 =
208 clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
209 ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
210 return CS0 | CS1;
211}
212
213} // namespace llvm
214
215static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
216 bool HeaderOnly, Cycle **CPtr = nullptr) {
217 if (!CI)
218 return true;
219 auto *BB = I->getParent();
220 auto *C = CI->getCycle(BB);
221 if (!C)
222 return false;
223 if (CPtr)
224 *CPtr = C;
225 return !HeaderOnly || BB == C->getHeader();
226}
227
228/// Checks if a type could have padding bytes.
229static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
230 // There is no size information, so be conservative.
231 if (!Ty->isSized())
232 return false;
233
234 // If the alloc size is not equal to the storage size, then there are padding
235 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
236 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
237 return false;
238
239 // FIXME: This isn't the right way to check for padding in vectors with
240 // non-byte-size elements.
241 if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
242 return isDenselyPacked(SeqTy->getElementType(), DL);
243
244 // For array types, check for padding within members.
245 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
246 return isDenselyPacked(SeqTy->getElementType(), DL);
247
248 if (!isa<StructType>(Ty))
249 return true;
250
251 // Check for padding within and between elements of a struct.
252 StructType *StructTy = cast<StructType>(Ty);
253 const StructLayout *Layout = DL.getStructLayout(StructTy);
254 uint64_t StartPos = 0;
255 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
256 Type *ElTy = StructTy->getElementType(I);
257 if (!isDenselyPacked(ElTy, DL))
258 return false;
259 if (StartPos != Layout->getElementOffsetInBits(I))
260 return false;
261 StartPos += DL.getTypeAllocSizeInBits(ElTy);
262 }
263
264 return true;
265}
266
267/// Get pointer operand of memory accessing instruction. If \p I is
268/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
269/// is set to false and the instruction is volatile, return nullptr.
271 bool AllowVolatile) {
272 if (!AllowVolatile && I->isVolatile())
273 return nullptr;
274
275 if (auto *LI = dyn_cast<LoadInst>(I)) {
276 return LI->getPointerOperand();
277 }
278
279 if (auto *SI = dyn_cast<StoreInst>(I)) {
280 return SI->getPointerOperand();
281 }
282
283 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
284 return CXI->getPointerOperand();
285 }
286
287 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
288 return RMWI->getPointerOperand();
289 }
290
291 return nullptr;
292}
293
294/// Helper function to create a pointer based on \p Ptr, and advanced by \p
295/// Offset bytes.
296static Value *constructPointer(Value *Ptr, int64_t Offset,
297 IRBuilder<NoFolder> &IRB) {
298 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
299 << "-bytes\n");
300
301 if (Offset)
302 Ptr = IRB.CreatePtrAdd(Ptr, IRB.getInt64(Offset),
303 Ptr->getName() + ".b" + Twine(Offset));
304 return Ptr;
305}
306
307static const Value *
309 const Value *Val, const DataLayout &DL, APInt &Offset,
310 bool GetMinOffset, bool AllowNonInbounds,
311 bool UseAssumed = false) {
312
313 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
314 const IRPosition &Pos = IRPosition::value(V);
315 // Only track dependence if we are going to use the assumed info.
316 const AAValueConstantRange *ValueConstantRangeAA =
317 A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
318 UseAssumed ? DepClassTy::OPTIONAL
320 if (!ValueConstantRangeAA)
321 return false;
322 ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()
323 : ValueConstantRangeAA->getKnown();
324 if (Range.isFullSet())
325 return false;
326
327 // We can only use the lower part of the range because the upper part can
328 // be higher than what the value can really be.
329 if (GetMinOffset)
330 ROffset = Range.getSignedMin();
331 else
332 ROffset = Range.getSignedMax();
333 return true;
334 };
335
336 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
337 /* AllowInvariant */ true,
338 AttributorAnalysis);
339}
340
341static const Value *
343 const Value *Ptr, int64_t &BytesOffset,
344 const DataLayout &DL, bool AllowNonInbounds = false) {
345 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
346 const Value *Base =
347 stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
348 /* GetMinOffset */ true, AllowNonInbounds);
349
350 BytesOffset = OffsetAPInt.getSExtValue();
351 return Base;
352}
353
354/// Clamp the information known for all returned values of a function
355/// (identified by \p QueryingAA) into \p S.
356template <typename AAType, typename StateType = typename AAType::StateType,
357 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
358 bool RecurseForSelectAndPHI = true>
360 Attributor &A, const AAType &QueryingAA, StateType &S,
361 const IRPosition::CallBaseContext *CBContext = nullptr) {
362 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
363 << QueryingAA << " into " << S << "\n");
364
365 assert((QueryingAA.getIRPosition().getPositionKind() ==
367 QueryingAA.getIRPosition().getPositionKind() ==
369 "Can only clamp returned value states for a function returned or call "
370 "site returned position!");
371
372 // Use an optional state as there might not be any return values and we want
373 // to join (IntegerState::operator&) the state of all there are.
374 std::optional<StateType> T;
375
376 // Callback for each possibly returned value.
377 auto CheckReturnValue = [&](Value &RV) -> bool {
378 const IRPosition &RVPos = IRPosition::value(RV, CBContext);
379 // If possible, use the hasAssumedIRAttr interface.
380 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
381 bool IsKnown;
383 A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);
384 }
385
386 const AAType *AA =
387 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
388 if (!AA)
389 return false;
390 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
391 << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");
392 const StateType &AAS = AA->getState();
393 if (!T)
394 T = StateType::getBestState(AAS);
395 *T &= AAS;
396 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
397 << "\n");
398 return T->isValidState();
399 };
400
401 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
403 RecurseForSelectAndPHI))
404 S.indicatePessimisticFixpoint();
405 else if (T)
406 S ^= *T;
407}
408
409namespace {
410/// Helper class for generic deduction: return value -> returned position.
411template <typename AAType, typename BaseType,
412 typename StateType = typename BaseType::StateType,
413 bool PropagateCallBaseContext = false,
414 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
415 bool RecurseForSelectAndPHI = true>
416struct AAReturnedFromReturnedValues : public BaseType {
417 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
418 : BaseType(IRP, A) {}
419
420 /// See AbstractAttribute::updateImpl(...).
421 ChangeStatus updateImpl(Attributor &A) override {
422 StateType S(StateType::getBestState(this->getState()));
423 clampReturnedValueStates<AAType, StateType, IRAttributeKind,
424 RecurseForSelectAndPHI>(
425 A, *this, S,
426 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
427 // TODO: If we know we visited all returned values, thus no are assumed
428 // dead, we can take the known information from the state T.
429 return clampStateAndIndicateChange<StateType>(this->getState(), S);
430 }
431};
432
433/// Clamp the information known at all call sites for a given argument
434/// (identified by \p QueryingAA) into \p S.
435template <typename AAType, typename StateType = typename AAType::StateType,
436 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
437static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
438 StateType &S) {
439 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
440 << QueryingAA << " into " << S << "\n");
441
442 assert(QueryingAA.getIRPosition().getPositionKind() ==
444 "Can only clamp call site argument states for an argument position!");
445
446 // Use an optional state as there might not be any return values and we want
447 // to join (IntegerState::operator&) the state of all there are.
448 std::optional<StateType> T;
449
450 // The argument number which is also the call site argument number.
451 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
452
453 auto CallSiteCheck = [&](AbstractCallSite ACS) {
454 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
455 // Check if a coresponding argument was found or if it is on not associated
456 // (which can happen for callback calls).
457 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
458 return false;
459
460 // If possible, use the hasAssumedIRAttr interface.
461 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
462 bool IsKnown;
464 A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);
465 }
466
467 const AAType *AA =
468 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
469 if (!AA)
470 return false;
471 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
472 << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos
473 << "\n");
474 const StateType &AAS = AA->getState();
475 if (!T)
476 T = StateType::getBestState(AAS);
477 *T &= AAS;
478 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
479 << "\n");
480 return T->isValidState();
481 };
482
483 bool UsedAssumedInformation = false;
484 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
485 UsedAssumedInformation))
486 S.indicatePessimisticFixpoint();
487 else if (T)
488 S ^= *T;
489}
490
491/// This function is the bridge between argument position and the call base
492/// context.
493template <typename AAType, typename BaseType,
494 typename StateType = typename AAType::StateType,
495 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
496bool getArgumentStateFromCallBaseContext(Attributor &A,
497 BaseType &QueryingAttribute,
498 IRPosition &Pos, StateType &State) {
500 "Expected an 'argument' position !");
501 const CallBase *CBContext = Pos.getCallBaseContext();
502 if (!CBContext)
503 return false;
504
505 int ArgNo = Pos.getCallSiteArgNo();
506 assert(ArgNo >= 0 && "Invalid Arg No!");
507 const IRPosition CBArgPos = IRPosition::callsite_argument(*CBContext, ArgNo);
508
509 // If possible, use the hasAssumedIRAttr interface.
510 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
511 bool IsKnown;
513 A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);
514 }
515
516 const auto *AA =
517 A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);
518 if (!AA)
519 return false;
520 const StateType &CBArgumentState =
521 static_cast<const StateType &>(AA->getState());
522
523 LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"
524 << "Position:" << Pos << "CB Arg state:" << CBArgumentState
525 << "\n");
526
527 // NOTE: If we want to do call site grouping it should happen here.
528 State ^= CBArgumentState;
529 return true;
530}
531
532/// Helper class for generic deduction: call site argument -> argument position.
533template <typename AAType, typename BaseType,
534 typename StateType = typename AAType::StateType,
535 bool BridgeCallBaseContext = false,
536 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
537struct AAArgumentFromCallSiteArguments : public BaseType {
538 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
539 : BaseType(IRP, A) {}
540
541 /// See AbstractAttribute::updateImpl(...).
542 ChangeStatus updateImpl(Attributor &A) override {
543 StateType S = StateType::getBestState(this->getState());
544
545 if (BridgeCallBaseContext) {
546 bool Success =
547 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,
548 IRAttributeKind>(
549 A, *this, this->getIRPosition(), S);
550 if (Success)
551 return clampStateAndIndicateChange<StateType>(this->getState(), S);
552 }
553 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,
554 S);
555
556 // TODO: If we know we visited all incoming values, thus no are assumed
557 // dead, we can take the known information from the state T.
558 return clampStateAndIndicateChange<StateType>(this->getState(), S);
559 }
560};
561
562/// Helper class for generic replication: function returned -> cs returned.
563template <typename AAType, typename BaseType,
564 typename StateType = typename BaseType::StateType,
565 bool IntroduceCallBaseContext = false,
566 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
567struct AACalleeToCallSite : public BaseType {
568 AACalleeToCallSite(const IRPosition &IRP, Attributor &A) : BaseType(IRP, A) {}
569
570 /// See AbstractAttribute::updateImpl(...).
571 ChangeStatus updateImpl(Attributor &A) override {
572 auto IRPKind = this->getIRPosition().getPositionKind();
574 IRPKind == IRPosition::IRP_CALL_SITE) &&
575 "Can only wrap function returned positions for call site "
576 "returned positions!");
577 auto &S = this->getState();
578
579 CallBase &CB = cast<CallBase>(this->getAnchorValue());
580 if (IntroduceCallBaseContext)
581 LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:" << CB
582 << "\n");
583
584 ChangeStatus Changed = ChangeStatus::UNCHANGED;
585 auto CalleePred = [&](ArrayRef<const Function *> Callees) {
586 for (const Function *Callee : Callees) {
587 IRPosition FnPos =
589 ? IRPosition::returned(*Callee,
590 IntroduceCallBaseContext ? &CB : nullptr)
591 : IRPosition::function(
592 *Callee, IntroduceCallBaseContext ? &CB : nullptr);
593 // If possible, use the hasAssumedIRAttr interface.
594 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
595 bool IsKnown;
597 A, this, FnPos, DepClassTy::REQUIRED, IsKnown))
598 return false;
599 continue;
600 }
601
602 const AAType *AA =
603 A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
604 if (!AA)
605 return false;
606 Changed |= clampStateAndIndicateChange(S, AA->getState());
607 if (S.isAtFixpoint())
608 return S.isValidState();
609 }
610 return true;
611 };
612 if (!A.checkForAllCallees(CalleePred, *this, CB))
613 return S.indicatePessimisticFixpoint();
614 return Changed;
615 }
616};
617
618/// Helper function to accumulate uses.
619template <class AAType, typename StateType = typename AAType::StateType>
620static void followUsesInContext(AAType &AA, Attributor &A,
622 const Instruction *CtxI,
624 StateType &State) {
625 auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
626 for (unsigned u = 0; u < Uses.size(); ++u) {
627 const Use *U = Uses[u];
628 if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
629 bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
630 if (Found && AA.followUseInMBEC(A, U, UserI, State))
631 Uses.insert_range(llvm::make_pointer_range(UserI->uses()));
632 }
633 }
634}
635
636/// Use the must-be-executed-context around \p I to add information into \p S.
637/// The AAType class is required to have `followUseInMBEC` method with the
638/// following signature and behaviour:
639///
640/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
641/// U - Underlying use.
642/// I - The user of the \p U.
643/// Returns true if the value should be tracked transitively.
644///
645template <class AAType, typename StateType = typename AAType::StateType>
646static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
647 Instruction &CtxI) {
648 const Value &Val = AA.getIRPosition().getAssociatedValue();
649 if (isa<ConstantData>(Val))
650 return;
651
653 A.getInfoCache().getMustBeExecutedContextExplorer();
654 if (!Explorer)
655 return;
656
657 // Container for (transitive) uses of the associated value.
659 for (const Use &U : Val.uses())
660 Uses.insert(&U);
661
662 followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);
663
664 if (S.isAtFixpoint())
665 return;
666
668 auto Pred = [&](const Instruction *I) {
669 if (const BranchInst *Br = dyn_cast<BranchInst>(I))
670 if (Br->isConditional())
671 BrInsts.push_back(Br);
672 return true;
673 };
674
675 // Here, accumulate conditional branch instructions in the context. We
676 // explore the child paths and collect the known states. The disjunction of
677 // those states can be merged to its own state. Let ParentState_i be a state
678 // to indicate the known information for an i-th branch instruction in the
679 // context. ChildStates are created for its successors respectively.
680 //
681 // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
682 // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
683 // ...
684 // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
685 //
686 // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
687 //
688 // FIXME: Currently, recursive branches are not handled. For example, we
689 // can't deduce that ptr must be dereferenced in below function.
690 //
691 // void f(int a, int c, int *ptr) {
692 // if(a)
693 // if (b) {
694 // *ptr = 0;
695 // } else {
696 // *ptr = 1;
697 // }
698 // else {
699 // if (b) {
700 // *ptr = 0;
701 // } else {
702 // *ptr = 1;
703 // }
704 // }
705 // }
706
707 Explorer->checkForAllContext(&CtxI, Pred);
708 for (const BranchInst *Br : BrInsts) {
709 StateType ParentState;
710
711 // The known state of the parent state is a conjunction of children's
712 // known states so it is initialized with a best state.
713 ParentState.indicateOptimisticFixpoint();
714
715 for (const BasicBlock *BB : Br->successors()) {
716 StateType ChildState;
717
718 size_t BeforeSize = Uses.size();
719 followUsesInContext(AA, A, *Explorer, &BB->front(), Uses, ChildState);
720
721 // Erase uses which only appear in the child.
722 for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
723 It = Uses.erase(It);
724
725 ParentState &= ChildState;
726 }
727
728 // Use only known state.
729 S += ParentState;
730 }
731}
732} // namespace
733
734/// ------------------------ PointerInfo ---------------------------------------
735
736namespace llvm {
737namespace AA {
738namespace PointerInfo {
739
740struct State;
741
742} // namespace PointerInfo
743} // namespace AA
744
745/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
746template <>
749 static inline Access getEmptyKey();
750 static inline Access getTombstoneKey();
751 static unsigned getHashValue(const Access &A);
752 static bool isEqual(const Access &LHS, const Access &RHS);
753};
754
755/// Helper that allows RangeTy as a key in a DenseMap.
756template <> struct DenseMapInfo<AA::RangeTy> {
757 static inline AA::RangeTy getEmptyKey() {
758 auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();
759 return AA::RangeTy{EmptyKey, EmptyKey};
760 }
761
762 static inline AA::RangeTy getTombstoneKey() {
763 auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();
764 return AA::RangeTy{TombstoneKey, TombstoneKey};
765 }
766
772
773 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
774 return A == B;
775 }
776};
777
778/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
779/// but the instruction
780struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
783 static inline Access getEmptyKey();
784 static inline Access getTombstoneKey();
785 static unsigned getHashValue(const Access &A);
786 static bool isEqual(const Access &LHS, const Access &RHS);
787};
788
789} // namespace llvm
790
791/// A type to track pointer/struct usage and accesses for AAPointerInfo.
793 /// Return the best possible representable state.
794 static State getBestState(const State &SIS) { return State(); }
795
796 /// Return the worst possible representable state.
797 static State getWorstState(const State &SIS) {
798 State R;
799 R.indicatePessimisticFixpoint();
800 return R;
801 }
802
803 State() = default;
804 State(State &&SIS) = default;
805
806 const State &getAssumed() const { return *this; }
807
808 /// See AbstractState::isValidState().
809 bool isValidState() const override { return BS.isValidState(); }
810
811 /// See AbstractState::isAtFixpoint().
812 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
813
814 /// See AbstractState::indicateOptimisticFixpoint().
816 BS.indicateOptimisticFixpoint();
818 }
819
820 /// See AbstractState::indicatePessimisticFixpoint().
822 BS.indicatePessimisticFixpoint();
824 }
825
826 State &operator=(const State &R) {
827 if (this == &R)
828 return *this;
829 BS = R.BS;
830 AccessList = R.AccessList;
831 OffsetBins = R.OffsetBins;
832 RemoteIMap = R.RemoteIMap;
833 ReturnedOffsets = R.ReturnedOffsets;
834 return *this;
835 }
836
838 if (this == &R)
839 return *this;
840 std::swap(BS, R.BS);
841 std::swap(AccessList, R.AccessList);
842 std::swap(OffsetBins, R.OffsetBins);
843 std::swap(RemoteIMap, R.RemoteIMap);
844 std::swap(ReturnedOffsets, R.ReturnedOffsets);
845 return *this;
846 }
847
848 /// Add a new Access to the state at offset \p Offset and with size \p Size.
849 /// The access is associated with \p I, writes \p Content (if anything), and
850 /// is of kind \p Kind. If an Access already exists for the same \p I and same
851 /// \p RemoteI, the two are combined, potentially losing information about
852 /// offset and size. The resulting access must now be moved from its original
853 /// OffsetBin to the bin for its new offset.
854 ///
855 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
857 Instruction &I, std::optional<Value *> Content,
859 Instruction *RemoteI = nullptr);
860
863 int64_t numOffsetBins() const { return OffsetBins.size(); }
864
865 const AAPointerInfo::Access &getAccess(unsigned Index) const {
866 return AccessList[Index];
867 }
868
869protected:
870 // Every memory instruction results in an Access object. We maintain a list of
871 // all Access objects that we own, along with the following maps:
872 //
873 // - OffsetBins: RangeTy -> { Access }
874 // - RemoteIMap: RemoteI x LocalI -> Access
875 //
876 // A RemoteI is any instruction that accesses memory. RemoteI is different
877 // from LocalI if and only if LocalI is a call; then RemoteI is some
878 // instruction in the callgraph starting from LocalI. Multiple paths in the
879 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
880 // are all combined into a single Access object. This may result in loss of
881 // information in RangeTy in the Access object.
885
886 /// Flag to determine if the underlying pointer is reaching a return statement
887 /// in the associated function or not. Returns in other functions cause
888 /// invalidation.
890
891 /// See AAPointerInfo::forallInterferingAccesses.
892 template <typename F>
894 if (!isValidState() || !ReturnedOffsets.isUnassigned())
895 return false;
896
897 for (const auto &It : OffsetBins) {
898 AA::RangeTy ItRange = It.getFirst();
899 if (!Range.mayOverlap(ItRange))
900 continue;
901 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
902 for (auto Index : It.getSecond()) {
903 auto &Access = AccessList[Index];
904 if (!CB(Access, IsExact))
905 return false;
906 }
907 }
908 return true;
909 }
910
911 /// See AAPointerInfo::forallInterferingAccesses.
912 template <typename F>
914 AA::RangeTy &Range) const {
915 if (!isValidState() || !ReturnedOffsets.isUnassigned())
916 return false;
917
918 auto LocalList = RemoteIMap.find(&I);
919 if (LocalList == RemoteIMap.end()) {
920 return true;
921 }
922
923 for (unsigned Index : LocalList->getSecond()) {
924 for (auto &R : AccessList[Index]) {
925 Range &= R;
926 if (Range.offsetAndSizeAreUnknown())
927 break;
928 }
929 }
931 }
932
933private:
934 /// State to track fixpoint and validity.
935 BooleanState BS;
936};
937
940 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
941 Instruction *RemoteI) {
942 RemoteI = RemoteI ? RemoteI : &I;
943
944 // Check if we have an access for this instruction, if not, simply add it.
945 auto &LocalList = RemoteIMap[RemoteI];
946 bool AccExists = false;
947 unsigned AccIndex = AccessList.size();
948 for (auto Index : LocalList) {
949 auto &A = AccessList[Index];
950 if (A.getLocalInst() == &I) {
951 AccExists = true;
952 AccIndex = Index;
953 break;
954 }
955 }
956
957 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
958 LLVM_DEBUG(if (ToAdd.size()) dbgs()
959 << "[AAPointerInfo] Inserting access in new offset bins\n";);
960
961 for (auto Key : ToAdd) {
962 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
963 OffsetBins[Key].insert(AccIndex);
964 }
965 };
966
967 if (!AccExists) {
968 AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
969 assert((AccessList.size() == AccIndex + 1) &&
970 "New Access should have been at AccIndex");
971 LocalList.push_back(AccIndex);
972 AddToBins(AccessList[AccIndex].getRanges());
974 }
975
976 // Combine the new Access with the existing Access, and then update the
977 // mapping in the offset bins.
978 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
979 auto &Current = AccessList[AccIndex];
980 auto Before = Current;
981 Current &= Acc;
982 if (Current == Before)
984
985 auto &ExistingRanges = Before.getRanges();
986 auto &NewRanges = Current.getRanges();
987
988 // Ranges that are in the old access but not the new access need to be removed
989 // from the offset bins.
991 AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
992 LLVM_DEBUG(if (ToRemove.size()) dbgs()
993 << "[AAPointerInfo] Removing access from old offset bins\n";);
994
995 for (auto Key : ToRemove) {
996 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
997 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
998 auto &Bin = OffsetBins[Key];
999 assert(Bin.count(AccIndex) &&
1000 "Expected bin to actually contain the Access.");
1001 Bin.erase(AccIndex);
1002 }
1003
1004 // Ranges that are in the new access but not the old access need to be added
1005 // to the offset bins.
1007 AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
1008 AddToBins(ToAdd);
1009 return ChangeStatus::CHANGED;
1010}
1011
1012namespace {
1013
1014#ifndef NDEBUG
1016 const AAPointerInfo::OffsetInfo &OI) {
1017 OS << llvm::interleaved_array(OI);
1018 return OS;
1019}
1020#endif // NDEBUG
1021
1022struct AAPointerInfoImpl
1023 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1025 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1026
1027 /// See AbstractAttribute::getAsStr().
1028 const std::string getAsStr(Attributor *A) const override {
1029 return std::string("PointerInfo ") +
1030 (isValidState() ? (std::string("#") +
1031 std::to_string(OffsetBins.size()) + " bins")
1032 : "<invalid>") +
1033 (reachesReturn()
1034 ? (" (returned:" +
1035 join(map_range(ReturnedOffsets,
1036 [](int64_t O) { return std::to_string(O); }),
1037 ", ") +
1038 ")")
1039 : "");
1040 }
1041
1042 /// See AbstractAttribute::manifest(...).
1043 ChangeStatus manifest(Attributor &A) override {
1044 return AAPointerInfo::manifest(A);
1045 }
1046
1047 const_bin_iterator begin() const override { return State::begin(); }
1048 const_bin_iterator end() const override { return State::end(); }
1049 int64_t numOffsetBins() const override { return State::numOffsetBins(); }
1050 bool reachesReturn() const override {
1051 return !ReturnedOffsets.isUnassigned();
1052 }
1053 void addReturnedOffsetsTo(OffsetInfo &OI) const override {
1054 if (ReturnedOffsets.isUnknown()) {
1055 OI.setUnknown();
1056 return;
1057 }
1058
1059 OffsetInfo MergedOI;
1060 for (auto Offset : ReturnedOffsets) {
1061 OffsetInfo TmpOI = OI;
1062 TmpOI.addToAll(Offset);
1063 MergedOI.merge(TmpOI);
1064 }
1065 OI = std::move(MergedOI);
1066 }
1067
1068 ChangeStatus setReachesReturn(const OffsetInfo &ReachedReturnedOffsets) {
1069 if (ReturnedOffsets.isUnknown())
1070 return ChangeStatus::UNCHANGED;
1071 if (ReachedReturnedOffsets.isUnknown()) {
1072 ReturnedOffsets.setUnknown();
1073 return ChangeStatus::CHANGED;
1074 }
1075 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1076 return ChangeStatus::CHANGED;
1077 return ChangeStatus::UNCHANGED;
1078 }
1079
1080 bool forallInterferingAccesses(
1081 AA::RangeTy Range,
1082 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1083 const override {
1084 return State::forallInterferingAccesses(Range, CB);
1085 }
1086
1087 bool forallInterferingAccesses(
1088 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1089 bool FindInterferingWrites, bool FindInterferingReads,
1090 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1091 AA::RangeTy &Range,
1092 function_ref<bool(const Access &)> SkipCB) const override {
1093 HasBeenWrittenTo = false;
1094
1095 SmallPtrSet<const Access *, 8> DominatingWrites;
1096 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1097
1098 Function &Scope = *I.getFunction();
1099 bool IsKnownNoSync;
1100 bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(
1101 A, &QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1102 IsKnownNoSync);
1103 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1104 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1105 bool AllInSameNoSyncFn = IsAssumedNoSync;
1106 bool InstIsExecutedByInitialThreadOnly =
1107 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1108
1109 // If the function is not ending in aligned barriers, we need the stores to
1110 // be in aligned barriers. The load being in one is not sufficient since the
1111 // store might be executed by a thread that disappears after, causing the
1112 // aligned barrier guarding the load to unblock and the load to read a value
1113 // that has no CFG path to the load.
1114 bool InstIsExecutedInAlignedRegion =
1115 FindInterferingReads && ExecDomainAA &&
1116 ExecDomainAA->isExecutedInAlignedRegion(A, I);
1117
1118 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1119 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1120
1121 InformationCache &InfoCache = A.getInfoCache();
1122 bool IsThreadLocalObj =
1123 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1124
1125 // Helper to determine if we need to consider threading, which we cannot
1126 // right now. However, if the function is (assumed) nosync or the thread
1127 // executing all instructions is the main thread only we can ignore
1128 // threading. Also, thread-local objects do not require threading reasoning.
1129 // Finally, we can ignore threading if either access is executed in an
1130 // aligned region.
1131 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1132 if (IsThreadLocalObj || AllInSameNoSyncFn)
1133 return true;
1134 const auto *FnExecDomainAA =
1135 I.getFunction() == &Scope
1136 ? ExecDomainAA
1137 : A.lookupAAFor<AAExecutionDomain>(
1138 IRPosition::function(*I.getFunction()), &QueryingAA,
1139 DepClassTy::NONE);
1140 if (!FnExecDomainAA)
1141 return false;
1142 if (InstIsExecutedInAlignedRegion ||
1143 (FindInterferingWrites &&
1144 FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {
1145 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1146 return true;
1147 }
1148 if (InstIsExecutedByInitialThreadOnly &&
1149 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1150 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1151 return true;
1152 }
1153 return false;
1154 };
1155
1156 // Helper to determine if the access is executed by the same thread as the
1157 // given instruction, for now it is sufficient to avoid any potential
1158 // threading effects as we cannot deal with them anyway.
1159 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1160 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1161 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1162 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1163 };
1164
1165 // TODO: Use inter-procedural reachability and dominance.
1166 bool IsKnownNoRecurse;
1168 A, this, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1169 IsKnownNoRecurse);
1170
1171 // TODO: Use reaching kernels from AAKernelInfo (or move it to
1172 // AAExecutionDomain) such that we allow scopes other than kernels as long
1173 // as the reaching kernels are disjoint.
1174 bool InstInKernel = A.getInfoCache().isKernel(Scope);
1175 bool ObjHasKernelLifetime = false;
1176 const bool UseDominanceReasoning =
1177 FindInterferingWrites && IsKnownNoRecurse;
1178 const DominatorTree *DT =
1179 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1180
1181 // Helper to check if a value has "kernel lifetime", that is it will not
1182 // outlive a GPU kernel. This is true for shared, constant, and local
1183 // globals on AMD and NVIDIA GPUs.
1184 auto HasKernelLifetime = [&](Value *V, Module &M) {
1185 if (!AA::isGPU(M))
1186 return false;
1187 switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {
1188 case AA::GPUAddressSpace::Shared:
1189 case AA::GPUAddressSpace::Constant:
1190 case AA::GPUAddressSpace::Local:
1191 return true;
1192 default:
1193 return false;
1194 };
1195 };
1196
1197 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1198 // to determine if we should look at reachability from the callee. For
1199 // certain pointers we know the lifetime and we do not have to step into the
1200 // callee to determine reachability as the pointer would be dead in the
1201 // callee. See the conditional initialization below.
1202 std::function<bool(const Function &)> IsLiveInCalleeCB;
1203
1204 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1205 // If the alloca containing function is not recursive the alloca
1206 // must be dead in the callee.
1207 const Function *AIFn = AI->getFunction();
1208 ObjHasKernelLifetime = A.getInfoCache().isKernel(*AIFn);
1209 bool IsKnownNoRecurse;
1211 A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL,
1212 IsKnownNoRecurse)) {
1213 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1214 }
1215 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1216 // If the global has kernel lifetime we can stop if we reach a kernel
1217 // as it is "dead" in the (unknown) callees.
1218 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1219 if (ObjHasKernelLifetime)
1220 IsLiveInCalleeCB = [&A](const Function &Fn) {
1221 return !A.getInfoCache().isKernel(Fn);
1222 };
1223 }
1224
1225 // Set of accesses/instructions that will overwrite the result and are
1226 // therefore blockers in the reachability traversal.
1227 AA::InstExclusionSetTy ExclusionSet;
1228
1229 auto AccessCB = [&](const Access &Acc, bool Exact) {
1230 Function *AccScope = Acc.getRemoteInst()->getFunction();
1231 bool AccInSameScope = AccScope == &Scope;
1232
1233 // If the object has kernel lifetime we can ignore accesses only reachable
1234 // by other kernels. For now we only skip accesses *in* other kernels.
1235 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1236 A.getInfoCache().isKernel(*AccScope))
1237 return true;
1238
1239 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1240 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1241 ExclusionSet.insert(Acc.getRemoteInst());
1242 }
1243
1244 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1245 (!FindInterferingReads || !Acc.isRead()))
1246 return true;
1247
1248 bool Dominates = FindInterferingWrites && DT && Exact &&
1249 Acc.isMustAccess() && AccInSameScope &&
1250 DT->dominates(Acc.getRemoteInst(), &I);
1251 if (Dominates)
1252 DominatingWrites.insert(&Acc);
1253
1254 // Track if all interesting accesses are in the same `nosync` function as
1255 // the given instruction.
1256 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1257
1258 InterferingAccesses.push_back({&Acc, Exact});
1259 return true;
1260 };
1261 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1262 return false;
1263
1264 HasBeenWrittenTo = !DominatingWrites.empty();
1265
1266 // Dominating writes form a chain, find the least/lowest member.
1267 Instruction *LeastDominatingWriteInst = nullptr;
1268 for (const Access *Acc : DominatingWrites) {
1269 if (!LeastDominatingWriteInst) {
1270 LeastDominatingWriteInst = Acc->getRemoteInst();
1271 } else if (DT->dominates(LeastDominatingWriteInst,
1272 Acc->getRemoteInst())) {
1273 LeastDominatingWriteInst = Acc->getRemoteInst();
1274 }
1275 }
1276
1277 // Helper to determine if we can skip a specific write access.
1278 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1279 if (SkipCB && SkipCB(Acc))
1280 return true;
1281 if (!CanIgnoreThreading(Acc))
1282 return false;
1283
1284 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1285 // If we successfully excluded all effects we are interested in, the
1286 // access can be skipped.
1287 bool ReadChecked = !FindInterferingReads;
1288 bool WriteChecked = !FindInterferingWrites;
1289
1290 // If the instruction cannot reach the access, the former does not
1291 // interfere with what the access reads.
1292 if (!ReadChecked) {
1293 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1294 &ExclusionSet, IsLiveInCalleeCB))
1295 ReadChecked = true;
1296 }
1297 // If the instruction cannot be reach from the access, the latter does not
1298 // interfere with what the instruction reads.
1299 if (!WriteChecked) {
1300 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1301 &ExclusionSet, IsLiveInCalleeCB))
1302 WriteChecked = true;
1303 }
1304
1305 // If we still might be affected by the write of the access but there are
1306 // dominating writes in the function of the instruction
1307 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1308 // by them. This would have happend above if they are all in the same
1309 // function, so we only check the inter-procedural case. Effectively, we
1310 // want to show that there is no call after the dominting write that might
1311 // reach the access, and when it returns reach the instruction with the
1312 // updated value. To this end, we iterate all call sites, check if they
1313 // might reach the instruction without going through another access
1314 // (ExclusionSet) and at the same time might reach the access. However,
1315 // that is all part of AAInterFnReachability.
1316 if (!WriteChecked && HasBeenWrittenTo &&
1317 Acc.getRemoteInst()->getFunction() != &Scope) {
1318
1319 const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1320 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1321 if (FnReachabilityAA) {
1322 // Without going backwards in the call tree, can we reach the access
1323 // from the least dominating write. Do not allow to pass the
1324 // instruction itself either.
1325 bool Inserted = ExclusionSet.insert(&I).second;
1326
1327 if (!FnReachabilityAA->instructionCanReach(
1328 A, *LeastDominatingWriteInst,
1329 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1330 WriteChecked = true;
1331
1332 if (Inserted)
1333 ExclusionSet.erase(&I);
1334 }
1335 }
1336
1337 if (ReadChecked && WriteChecked)
1338 return true;
1339
1340 if (!DT || !UseDominanceReasoning)
1341 return false;
1342 if (!DominatingWrites.count(&Acc))
1343 return false;
1344 return LeastDominatingWriteInst != Acc.getRemoteInst();
1345 };
1346
1347 // Run the user callback on all accesses we cannot skip and return if
1348 // that succeeded for all or not.
1349 for (auto &It : InterferingAccesses) {
1350 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1351 !CanSkipAccess(*It.first, It.second)) {
1352 if (!UserCB(*It.first, It.second))
1353 return false;
1354 }
1355 }
1356 return true;
1357 }
1358
1359 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1360 const AAPointerInfo &OtherAA,
1361 CallBase &CB) {
1362 using namespace AA::PointerInfo;
1363 if (!OtherAA.getState().isValidState() || !isValidState())
1364 return indicatePessimisticFixpoint();
1365
1366 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1367 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1368 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1369 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1370
1371 // Combine the accesses bin by bin.
1372 const auto &State = OtherAAImpl.getState();
1373 for (const auto &It : State) {
1374 for (auto Index : It.getSecond()) {
1375 const auto &RAcc = State.getAccess(Index);
1376 if (IsByval && !RAcc.isRead())
1377 continue;
1378 bool UsedAssumedInformation = false;
1379 AccessKind AK = RAcc.getKind();
1380 auto Content = A.translateArgumentToCallSiteContent(
1381 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1382 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1383 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1384
1385 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1386 RAcc.getType(), RAcc.getRemoteInst());
1387 }
1388 }
1389 return Changed;
1390 }
1391
1392 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1393 const OffsetInfo &Offsets, CallBase &CB,
1394 bool IsMustAcc) {
1395 using namespace AA::PointerInfo;
1396 if (!OtherAA.getState().isValidState() || !isValidState())
1397 return indicatePessimisticFixpoint();
1398
1399 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1400
1401 // Combine the accesses bin by bin.
1402 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1403 const auto &State = OtherAAImpl.getState();
1404 for (const auto &It : State) {
1405 for (auto Index : It.getSecond()) {
1406 const auto &RAcc = State.getAccess(Index);
1407 if (!IsMustAcc && RAcc.isAssumption())
1408 continue;
1409 for (auto Offset : Offsets) {
1410 auto NewRanges = Offset == AA::RangeTy::Unknown
1412 : RAcc.getRanges();
1413 if (!NewRanges.isUnknown()) {
1414 NewRanges.addToAllOffsets(Offset);
1415 }
1416 AccessKind AK = RAcc.getKind();
1417 if (!IsMustAcc)
1418 AK = AccessKind((AK & ~AK_MUST) | AK_MAY);
1419 Changed |= addAccess(A, NewRanges, CB, RAcc.getContent(), AK,
1420 RAcc.getType(), RAcc.getRemoteInst());
1421 }
1422 }
1423 }
1424 return Changed;
1425 }
1426
1427 /// Statistic tracking for all AAPointerInfo implementations.
1428 /// See AbstractAttribute::trackStatistics().
1429 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1430
1431 /// Dump the state into \p O.
1432 void dumpState(raw_ostream &O) {
1433 for (auto &It : OffsetBins) {
1434 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1435 << "] : " << It.getSecond().size() << "\n";
1436 for (auto AccIndex : It.getSecond()) {
1437 auto &Acc = AccessList[AccIndex];
1438 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1439 if (Acc.getLocalInst() != Acc.getRemoteInst())
1440 O << " --> " << *Acc.getRemoteInst()
1441 << "\n";
1442 if (!Acc.isWrittenValueYetUndetermined()) {
1443 if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
1444 O << " - c: func " << Acc.getWrittenValue()->getName()
1445 << "\n";
1446 else if (Acc.getWrittenValue())
1447 O << " - c: " << *Acc.getWrittenValue() << "\n";
1448 else
1449 O << " - c: <unknown>\n";
1450 }
1451 }
1452 }
1453 }
1454};
1455
1456struct AAPointerInfoFloating : public AAPointerInfoImpl {
1458 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1459 : AAPointerInfoImpl(IRP, A) {}
1460
1461 /// Deal with an access and signal if it was handled successfully.
1462 bool handleAccess(Attributor &A, Instruction &I,
1463 std::optional<Value *> Content, AccessKind Kind,
1464 OffsetInfo::VecTy &Offsets, ChangeStatus &Changed,
1465 Type &Ty) {
1466 using namespace AA::PointerInfo;
1468 const DataLayout &DL = A.getDataLayout();
1469 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1470 if (!AccessSize.isScalable())
1471 Size = AccessSize.getFixedValue();
1472
1473 // Make a strictly ascending list of offsets as required by addAccess()
1474 SmallVector<int64_t> OffsetsSorted(Offsets.begin(), Offsets.end());
1475 llvm::sort(OffsetsSorted);
1476
1478 if (!VT || VT->getElementCount().isScalable() ||
1479 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1480 (*Content)->getType() != VT ||
1481 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1482 Changed =
1483 Changed | addAccess(A, {OffsetsSorted, Size}, I, Content, Kind, &Ty);
1484 } else {
1485 // Handle vector stores with constant content element-wise.
1486 // TODO: We could look for the elements or create instructions
1487 // representing them.
1488 // TODO: We need to push the Content into the range abstraction
1489 // (AA::RangeTy) to allow different content values for different
1490 // ranges. ranges. Hence, support vectors storing different values.
1491 Type *ElementType = VT->getElementType();
1492 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1493 auto *ConstContent = cast<Constant>(*Content);
1494 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1495 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1496
1497 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1498 Value *ElementContent = ConstantExpr::getExtractElement(
1499 ConstContent, ConstantInt::get(Int32Ty, i));
1500
1501 // Add the element access.
1502 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1503 ElementContent, Kind, ElementType);
1504
1505 // Advance the offsets for the next element.
1506 for (auto &ElementOffset : ElementOffsets)
1507 ElementOffset += ElementSize;
1508 }
1509 }
1510 return true;
1511 };
1512
1513 /// See AbstractAttribute::updateImpl(...).
1514 ChangeStatus updateImpl(Attributor &A) override;
1515
1516 /// If the indices to \p GEP can be traced to constants, incorporate all
1517 /// of these into \p UsrOI.
1518 ///
1519 /// \return true iff \p UsrOI is updated.
1520 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1521 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1522 const GEPOperator *GEP);
1523
1524 /// See AbstractAttribute::trackStatistics()
1525 void trackStatistics() const override {
1526 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1527 }
1528};
1529
1530bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1531 const DataLayout &DL,
1532 OffsetInfo &UsrOI,
1533 const OffsetInfo &PtrOI,
1534 const GEPOperator *GEP) {
1535 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1536 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1537 APInt ConstantOffset(BitWidth, 0);
1538
1539 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1540 "Don't look for constant values if the offset has already been "
1541 "determined to be unknown.");
1542
1543 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1544 UsrOI.setUnknown();
1545 return true;
1546 }
1547
1548 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
1549 << (VariableOffsets.empty() ? "" : "not") << " constant "
1550 << *GEP << "\n");
1551
1552 auto Union = PtrOI;
1553 Union.addToAll(ConstantOffset.getSExtValue());
1554
1555 // Each VI in VariableOffsets has a set of potential constant values. Every
1556 // combination of elements, picked one each from these sets, is separately
1557 // added to the original set of offsets, thus resulting in more offsets.
1558 for (const auto &VI : VariableOffsets) {
1559 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1560 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1561 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1562 UsrOI.setUnknown();
1563 return true;
1564 }
1565
1566 // UndefValue is treated as a zero, which leaves Union as is.
1567 if (PotentialConstantsAA->undefIsContained())
1568 continue;
1569
1570 // We need at least one constant in every set to compute an actual offset.
1571 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1572 // don't actually exist. In other words, the absence of constant values
1573 // implies that the operation can be assumed dead for now.
1574 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1575 if (AssumedSet.empty())
1576 return false;
1577
1578 OffsetInfo Product;
1579 for (const auto &ConstOffset : AssumedSet) {
1580 auto CopyPerOffset = Union;
1581 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1582 VI.second.getZExtValue());
1583 Product.merge(CopyPerOffset);
1584 }
1585 Union = Product;
1586 }
1587
1588 UsrOI = std::move(Union);
1589 return true;
1590}
1591
1592ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1593 using namespace AA::PointerInfo;
1595 const DataLayout &DL = A.getDataLayout();
1596 Value &AssociatedValue = getAssociatedValue();
1597
1598 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1599 OffsetInfoMap[&AssociatedValue].insert(0);
1600
1601 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1602 // One does not simply walk into a map and assign a reference to a possibly
1603 // new location. That can cause an invalidation before the assignment
1604 // happens, like so:
1605 //
1606 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1607 //
1608 // The RHS is a reference that may be invalidated by an insertion caused by
1609 // the LHS. So we ensure that the side-effect of the LHS happens first.
1610
1611 assert(OffsetInfoMap.contains(CurPtr) &&
1612 "CurPtr does not exist in the map!");
1613
1614 auto &UsrOI = OffsetInfoMap[Usr];
1615 auto &PtrOI = OffsetInfoMap[CurPtr];
1616 assert(!PtrOI.isUnassigned() &&
1617 "Cannot pass through if the input Ptr was not visited!");
1618 UsrOI.merge(PtrOI);
1619 Follow = true;
1620 return true;
1621 };
1622
1623 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1624 Value *CurPtr = U.get();
1625 User *Usr = U.getUser();
1626 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
1627 << "\n");
1628 assert(OffsetInfoMap.count(CurPtr) &&
1629 "The current pointer offset should have been seeded!");
1630 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1631 "Current pointer should be assigned");
1632
1633 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1634 if (CE->isCast())
1635 return HandlePassthroughUser(Usr, CurPtr, Follow);
1636 if (!isa<GEPOperator>(CE)) {
1637 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE
1638 << "\n");
1639 return false;
1640 }
1641 }
1642 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1643 // Note the order here, the Usr access might change the map, CurPtr is
1644 // already in it though.
1645 auto &UsrOI = OffsetInfoMap[Usr];
1646 auto &PtrOI = OffsetInfoMap[CurPtr];
1647
1648 if (UsrOI.isUnknown())
1649 return true;
1650
1651 if (PtrOI.isUnknown()) {
1652 Follow = true;
1653 UsrOI.setUnknown();
1654 return true;
1655 }
1656
1657 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1658 return true;
1659 }
1660 if (isa<PtrToIntInst>(Usr))
1661 return false;
1662 if (isa<CastInst>(Usr) || isa<SelectInst>(Usr))
1663 return HandlePassthroughUser(Usr, CurPtr, Follow);
1664 // Returns are allowed if they are in the associated functions. Users can
1665 // then check the call site return. Returns from other functions can't be
1666 // tracked and are cause for invalidation.
1667 if (auto *RI = dyn_cast<ReturnInst>(Usr)) {
1668 if (RI->getFunction() == getAssociatedFunction()) {
1669 auto &PtrOI = OffsetInfoMap[CurPtr];
1670 Changed |= setReachesReturn(PtrOI);
1671 return true;
1672 }
1673 return false;
1674 }
1675
1676 // For PHIs we need to take care of the recurrence explicitly as the value
1677 // might change while we iterate through a loop. For now, we give up if
1678 // the PHI is not invariant.
1679 if (auto *PHI = dyn_cast<PHINode>(Usr)) {
1680 // Note the order here, the Usr access might change the map, CurPtr is
1681 // already in it though.
1682 auto [PhiIt, IsFirstPHIUser] = OffsetInfoMap.try_emplace(PHI);
1683 auto &UsrOI = PhiIt->second;
1684 auto &PtrOI = OffsetInfoMap[CurPtr];
1685
1686 // Check if the PHI operand has already an unknown offset as we can't
1687 // improve on that anymore.
1688 if (PtrOI.isUnknown()) {
1689 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
1690 << *CurPtr << " in " << *PHI << "\n");
1691 Follow = !UsrOI.isUnknown();
1692 UsrOI.setUnknown();
1693 return true;
1694 }
1695
1696 // Check if the PHI is invariant (so far).
1697 if (UsrOI == PtrOI) {
1698 assert(!PtrOI.isUnassigned() &&
1699 "Cannot assign if the current Ptr was not visited!");
1700 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
1701 return true;
1702 }
1703
1704 // Check if the PHI operand can be traced back to AssociatedValue.
1705 APInt Offset(
1706 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1707 0);
1708 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1709 DL, Offset, /* AllowNonInbounds */ true);
1710 auto It = OffsetInfoMap.find(CurPtrBase);
1711 if (It == OffsetInfoMap.end()) {
1712 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
1713 << *CurPtr << " in " << *PHI
1714 << " (base: " << *CurPtrBase << ")\n");
1715 UsrOI.setUnknown();
1716 Follow = true;
1717 return true;
1718 }
1719
1720 // Check if the PHI operand is not dependent on the PHI itself. Every
1721 // recurrence is a cyclic net of PHIs in the data flow, and has an
1722 // equivalent Cycle in the control flow. One of those PHIs must be in the
1723 // header of that control flow Cycle. This is independent of the choice of
1724 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1725 // every Cycle header; if such a node is marked unknown, this will
1726 // eventually propagate through the whole net of PHIs in the recurrence.
1727 const auto *CI =
1728 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1729 *PHI->getFunction());
1730 if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {
1731 auto BaseOI = It->getSecond();
1732 BaseOI.addToAll(Offset.getZExtValue());
1733 if (IsFirstPHIUser || BaseOI == UsrOI) {
1734 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
1735 << " in " << *Usr << "\n");
1736 return HandlePassthroughUser(Usr, CurPtr, Follow);
1737 }
1738
1739 LLVM_DEBUG(
1740 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
1741 << *CurPtr << " in " << *PHI << "\n");
1742 UsrOI.setUnknown();
1743 Follow = true;
1744 return true;
1745 }
1746
1747 UsrOI.merge(PtrOI);
1748 Follow = true;
1749 return true;
1750 }
1751
1752 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1753 // If the access is to a pointer that may or may not be the associated
1754 // value, e.g. due to a PHI, we cannot assume it will be read.
1755 AccessKind AK = AccessKind::AK_R;
1756 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1757 AK = AccessKind(AK | AccessKind::AK_MUST);
1758 else
1759 AK = AccessKind(AK | AccessKind::AK_MAY);
1760 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1761 OffsetInfoMap[CurPtr].Offsets, Changed,
1762 *LoadI->getType()))
1763 return false;
1764
1765 auto IsAssumption = [](Instruction &I) {
1766 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1767 return II->isAssumeLikeIntrinsic();
1768 return false;
1769 };
1770
1771 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1772 // Check if the assumption and the load are executed together without
1773 // memory modification.
1774 do {
1775 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1776 return true;
1777 FromI = FromI->getNextNode();
1778 } while (FromI && FromI != ToI);
1779 return false;
1780 };
1781
1782 BasicBlock *BB = LoadI->getParent();
1783 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1784 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1785 return false;
1786 BasicBlock *IntrBB = IntrI.getParent();
1787 if (IntrI.getParent() == BB) {
1788 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1789 return false;
1790 } else {
1791 auto PredIt = pred_begin(IntrBB);
1792 if (PredIt == pred_end(IntrBB))
1793 return false;
1794 if ((*PredIt) != BB)
1795 return false;
1796 if (++PredIt != pred_end(IntrBB))
1797 return false;
1798 for (auto *SuccBB : successors(BB)) {
1799 if (SuccBB == IntrBB)
1800 continue;
1801 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1802 continue;
1803 return false;
1804 }
1805 if (IsImpactedInRange(LoadI->getNextNode(), BB->getTerminator()))
1806 return false;
1807 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1808 return false;
1809 }
1810 return true;
1811 };
1812
1813 std::pair<Value *, IntrinsicInst *> Assumption;
1814 for (const Use &LoadU : LoadI->uses()) {
1815 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1816 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1817 continue;
1818 for (const Use &CmpU : CmpI->uses()) {
1819 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1820 if (!IsValidAssume(*IntrI))
1821 continue;
1822 int Idx = CmpI->getOperandUse(0) == LoadU;
1823 Assumption = {CmpI->getOperand(Idx), IntrI};
1824 break;
1825 }
1826 }
1827 }
1828 if (Assumption.first)
1829 break;
1830 }
1831
1832 // Check if we found an assumption associated with this load.
1833 if (!Assumption.first || !Assumption.second)
1834 return true;
1835
1836 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
1837 << *Assumption.second << ": " << *LoadI
1838 << " == " << *Assumption.first << "\n");
1839 bool UsedAssumedInformation = false;
1840 std::optional<Value *> Content = nullptr;
1841 if (Assumption.first)
1842 Content =
1843 A.getAssumedSimplified(*Assumption.first, *this,
1844 UsedAssumedInformation, AA::Interprocedural);
1845 return handleAccess(
1846 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1847 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1848 }
1849
1850 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1851 ArrayRef<Value *> OtherOps, AccessKind AK) {
1852 for (auto *OtherOp : OtherOps) {
1853 if (OtherOp == CurPtr) {
1854 LLVM_DEBUG(
1855 dbgs()
1856 << "[AAPointerInfo] Escaping use in store like instruction " << I
1857 << "\n");
1858 return false;
1859 }
1860 }
1861
1862 // If the access is to a pointer that may or may not be the associated
1863 // value, e.g. due to a PHI, we cannot assume it will be written.
1864 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1865 AK = AccessKind(AK | AccessKind::AK_MUST);
1866 else
1867 AK = AccessKind(AK | AccessKind::AK_MAY);
1868 bool UsedAssumedInformation = false;
1869 std::optional<Value *> Content = nullptr;
1870 if (ValueOp)
1871 Content = A.getAssumedSimplified(
1872 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1873 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1874 Changed, ValueTy);
1875 };
1876
1877 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1878 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1879 *StoreI->getValueOperand()->getType(),
1880 {StoreI->getValueOperand()}, AccessKind::AK_W);
1881 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1882 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1883 {RMWI->getValOperand()}, AccessKind::AK_RW);
1884 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1885 return HandleStoreLike(
1886 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1887 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1888 AccessKind::AK_RW);
1889
1890 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1891 if (CB->isLifetimeStartOrEnd())
1892 return true;
1893 const auto *TLI =
1894 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->getFunction());
1895 if (getFreedOperand(CB, TLI) == U)
1896 return true;
1897 if (CB->isArgOperand(&U)) {
1898 unsigned ArgNo = CB->getArgOperandNo(&U);
1899 const auto *CSArgPI = A.getAAFor<AAPointerInfo>(
1900 *this, IRPosition::callsite_argument(*CB, ArgNo),
1902 if (!CSArgPI)
1903 return false;
1904 bool IsArgMustAcc = (getUnderlyingObject(CurPtr) == &AssociatedValue);
1905 Changed = translateAndAddState(A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1906 IsArgMustAcc) |
1907 Changed;
1908 if (!CSArgPI->reachesReturn())
1909 return isValidState();
1910
1912 if (!Callee || Callee->arg_size() <= ArgNo)
1913 return false;
1914 bool UsedAssumedInformation = false;
1915 auto ReturnedValue = A.getAssumedSimplified(
1916 IRPosition::returned(*Callee), *this, UsedAssumedInformation,
1918 auto *ReturnedArg =
1919 dyn_cast_or_null<Argument>(ReturnedValue.value_or(nullptr));
1920 auto *Arg = Callee->getArg(ArgNo);
1921 if (ReturnedArg && Arg != ReturnedArg)
1922 return true;
1923 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1924 const auto *CSRetPI = A.getAAFor<AAPointerInfo>(
1926 if (!CSRetPI)
1927 return false;
1928 OffsetInfo OI = OffsetInfoMap[CurPtr];
1929 CSArgPI->addReturnedOffsetsTo(OI);
1930 Changed =
1931 translateAndAddState(A, *CSRetPI, OI, *CB, IsRetMustAcc) | Changed;
1932 return isValidState();
1933 }
1934 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
1935 << "\n");
1936 return false;
1937 }
1938
1939 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
1940 return false;
1941 };
1942 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1943 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
1944 assert(!OffsetInfoMap[OldU].isUnassigned() && "Old use should be assinged");
1945 if (OffsetInfoMap.count(NewU)) {
1946 LLVM_DEBUG({
1947 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1948 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
1949 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
1950 << "\n";
1951 }
1952 });
1953 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1954 }
1955 bool Unused;
1956 return HandlePassthroughUser(NewU.get(), OldU.get(), Unused);
1957 };
1958 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1959 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1960 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1961 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
1962 return indicatePessimisticFixpoint();
1963 }
1964
1965 LLVM_DEBUG({
1966 dbgs() << "Accesses by bin after update:\n";
1967 dumpState(dbgs());
1968 });
1969
1970 return Changed;
1971}
1972
1973struct AAPointerInfoReturned final : AAPointerInfoImpl {
1974 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1975 : AAPointerInfoImpl(IRP, A) {}
1976
1977 /// See AbstractAttribute::updateImpl(...).
1978 ChangeStatus updateImpl(Attributor &A) override {
1979 return indicatePessimisticFixpoint();
1980 }
1981
1982 /// See AbstractAttribute::trackStatistics()
1983 void trackStatistics() const override {
1984 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1985 }
1986};
1987
1988struct AAPointerInfoArgument final : AAPointerInfoFloating {
1989 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1990 : AAPointerInfoFloating(IRP, A) {}
1991
1992 /// See AbstractAttribute::trackStatistics()
1993 void trackStatistics() const override {
1994 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1995 }
1996};
1997
1998struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1999 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
2000 : AAPointerInfoFloating(IRP, A) {}
2001
2002 /// See AbstractAttribute::updateImpl(...).
2003 ChangeStatus updateImpl(Attributor &A) override {
2004 using namespace AA::PointerInfo;
2005 // We handle memory intrinsics explicitly, at least the first (=
2006 // destination) and second (=source) arguments as we know how they are
2007 // accessed.
2008 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
2009 int64_t LengthVal = AA::RangeTy::Unknown;
2010 if (auto Length = MI->getLengthInBytes())
2011 LengthVal = Length->getSExtValue();
2012 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
2013 ChangeStatus Changed = ChangeStatus::UNCHANGED;
2014 if (ArgNo > 1) {
2015 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
2016 << *MI << "\n");
2017 return indicatePessimisticFixpoint();
2018 } else {
2019 auto Kind =
2020 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
2021 Changed =
2022 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
2023 }
2024 LLVM_DEBUG({
2025 dbgs() << "Accesses by bin after update:\n";
2026 dumpState(dbgs());
2027 });
2028
2029 return Changed;
2030 }
2031
2032 // TODO: Once we have call site specific value information we can provide
2033 // call site specific liveness information and then it makes
2034 // sense to specialize attributes for call sites arguments instead of
2035 // redirecting requests to the callee argument.
2036 Argument *Arg = getAssociatedArgument();
2037 if (Arg) {
2038 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2039 auto *ArgAA =
2040 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
2041 if (ArgAA && ArgAA->getState().isValidState())
2042 return translateAndAddStateFromCallee(A, *ArgAA,
2043 *cast<CallBase>(getCtxI()));
2044 if (!Arg->getParent()->isDeclaration())
2045 return indicatePessimisticFixpoint();
2046 }
2047
2048 bool IsKnownNoCapture;
2050 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2051 return indicatePessimisticFixpoint();
2052
2053 bool IsKnown = false;
2054 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
2055 return ChangeStatus::UNCHANGED;
2056 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
2057 auto Kind =
2058 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2059 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
2060 nullptr);
2061 }
2062
2063 /// See AbstractAttribute::trackStatistics()
2064 void trackStatistics() const override {
2065 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2066 }
2067};
2068
2069struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2070 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
2071 : AAPointerInfoFloating(IRP, A) {}
2072
2073 /// See AbstractAttribute::trackStatistics()
2074 void trackStatistics() const override {
2075 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2076 }
2077};
2078} // namespace
2079
2080/// -----------------------NoUnwind Function Attribute--------------------------
2081
2082namespace {
2083struct AANoUnwindImpl : AANoUnwind {
2084 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
2085
2086 /// See AbstractAttribute::initialize(...).
2087 void initialize(Attributor &A) override {
2088 bool IsKnown;
2090 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2091 (void)IsKnown;
2092 }
2093
2094 const std::string getAsStr(Attributor *A) const override {
2095 return getAssumed() ? "nounwind" : "may-unwind";
2096 }
2097
2098 /// See AbstractAttribute::updateImpl(...).
2099 ChangeStatus updateImpl(Attributor &A) override {
2100 auto Opcodes = {
2101 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
2102 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
2103 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
2104
2105 auto CheckForNoUnwind = [&](Instruction &I) {
2106 if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
2107 return true;
2108
2109 if (const auto *CB = dyn_cast<CallBase>(&I)) {
2110 bool IsKnownNoUnwind;
2112 A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
2113 IsKnownNoUnwind);
2114 }
2115 return false;
2116 };
2117
2118 bool UsedAssumedInformation = false;
2119 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
2120 UsedAssumedInformation))
2121 return indicatePessimisticFixpoint();
2122
2123 return ChangeStatus::UNCHANGED;
2124 }
2125};
2126
2127struct AANoUnwindFunction final : public AANoUnwindImpl {
2128 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
2129 : AANoUnwindImpl(IRP, A) {}
2130
2131 /// See AbstractAttribute::trackStatistics()
2132 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
2133};
2134
2135/// NoUnwind attribute deduction for a call sites.
2136struct AANoUnwindCallSite final
2137 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2138 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2139 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP, A) {}
2140
2141 /// See AbstractAttribute::trackStatistics()
2142 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
2143};
2144} // namespace
2145
2146/// ------------------------ NoSync Function Attribute -------------------------
2147
2148bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2149 switch (CB.getIntrinsicID()) {
2150 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2151 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2152 case Intrinsic::nvvm_barrier0_and:
2153 case Intrinsic::nvvm_barrier0_or:
2154 case Intrinsic::nvvm_barrier0_popc:
2155 return true;
2156 case Intrinsic::amdgcn_s_barrier:
2157 if (ExecutedAligned)
2158 return true;
2159 break;
2160 default:
2161 break;
2162 }
2163 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2164}
2165
2167 if (!I->isAtomic())
2168 return false;
2169
2170 if (auto *FI = dyn_cast<FenceInst>(I))
2171 // All legal orderings for fence are stronger than monotonic.
2172 return FI->getSyncScopeID() != SyncScope::SingleThread;
2173 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2174 // Unordered is not a legal ordering for cmpxchg.
2175 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2176 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2177 }
2178
2179 AtomicOrdering Ordering;
2180 switch (I->getOpcode()) {
2181 case Instruction::AtomicRMW:
2182 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2183 break;
2184 case Instruction::Store:
2185 Ordering = cast<StoreInst>(I)->getOrdering();
2186 break;
2187 case Instruction::Load:
2188 Ordering = cast<LoadInst>(I)->getOrdering();
2189 break;
2190 default:
2192 "New atomic operations need to be known in the attributor.");
2193 }
2194
2195 return (Ordering != AtomicOrdering::Unordered &&
2196 Ordering != AtomicOrdering::Monotonic);
2197}
2198
2199/// Return true if this intrinsic is nosync. This is only used for intrinsics
2200/// which would be nosync except that they have a volatile flag. All other
2201/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
2203 if (auto *MI = dyn_cast<MemIntrinsic>(I))
2204 return !MI->isVolatile();
2205 return false;
2206}
2207
2208namespace {
2209struct AANoSyncImpl : AANoSync {
2210 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2211
2212 /// See AbstractAttribute::initialize(...).
2213 void initialize(Attributor &A) override {
2214 bool IsKnown;
2215 assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),
2216 DepClassTy::NONE, IsKnown));
2217 (void)IsKnown;
2218 }
2219
2220 const std::string getAsStr(Attributor *A) const override {
2221 return getAssumed() ? "nosync" : "may-sync";
2222 }
2223
2224 /// See AbstractAttribute::updateImpl(...).
2225 ChangeStatus updateImpl(Attributor &A) override;
2226};
2227
2228ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2229
2230 auto CheckRWInstForNoSync = [&](Instruction &I) {
2231 return AA::isNoSyncInst(A, I, *this);
2232 };
2233
2234 auto CheckForNoSync = [&](Instruction &I) {
2235 // At this point we handled all read/write effects and they are all
2236 // nosync, so they can be skipped.
2237 if (I.mayReadOrWriteMemory())
2238 return true;
2239
2240 bool IsKnown;
2241 CallBase &CB = cast<CallBase>(I);
2244 IsKnown))
2245 return true;
2246
2247 // non-convergent and readnone imply nosync.
2248 return !CB.isConvergent();
2249 };
2250
2251 bool UsedAssumedInformation = false;
2252 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2253 UsedAssumedInformation) ||
2254 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2255 UsedAssumedInformation))
2256 return indicatePessimisticFixpoint();
2257
2259}
2260
2261struct AANoSyncFunction final : public AANoSyncImpl {
2262 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2263 : AANoSyncImpl(IRP, A) {}
2264
2265 /// See AbstractAttribute::trackStatistics()
2266 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
2267};
2268
2269/// NoSync attribute deduction for a call sites.
2270struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2271 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2272 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP, A) {}
2273
2274 /// See AbstractAttribute::trackStatistics()
2275 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
2276};
2277} // namespace
2278
2279/// ------------------------ No-Free Attributes ----------------------------
2280
2281namespace {
2282struct AANoFreeImpl : public AANoFree {
2283 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2284
2285 /// See AbstractAttribute::initialize(...).
2286 void initialize(Attributor &A) override {
2287 bool IsKnown;
2288 assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),
2289 DepClassTy::NONE, IsKnown));
2290 (void)IsKnown;
2291 }
2292
2293 /// See AbstractAttribute::updateImpl(...).
2294 ChangeStatus updateImpl(Attributor &A) override {
2295 auto CheckForNoFree = [&](Instruction &I) {
2296 bool IsKnown;
2299 DepClassTy::REQUIRED, IsKnown);
2300 };
2301
2302 bool UsedAssumedInformation = false;
2303 if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2304 UsedAssumedInformation))
2305 return indicatePessimisticFixpoint();
2306 return ChangeStatus::UNCHANGED;
2307 }
2308
2309 /// See AbstractAttribute::getAsStr().
2310 const std::string getAsStr(Attributor *A) const override {
2311 return getAssumed() ? "nofree" : "may-free";
2312 }
2313};
2314
2315struct AANoFreeFunction final : public AANoFreeImpl {
2316 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2317 : AANoFreeImpl(IRP, A) {}
2318
2319 /// See AbstractAttribute::trackStatistics()
2320 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
2321};
2322
2323/// NoFree attribute deduction for a call sites.
2324struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2325 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2326 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP, A) {}
2327
2328 /// See AbstractAttribute::trackStatistics()
2329 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
2330};
2331
2332/// NoFree attribute for floating values.
2333struct AANoFreeFloating : AANoFreeImpl {
2334 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2335 : AANoFreeImpl(IRP, A) {}
2336
2337 /// See AbstractAttribute::trackStatistics()
2338 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
2339
2340 /// See Abstract Attribute::updateImpl(...).
2341 ChangeStatus updateImpl(Attributor &A) override {
2342 const IRPosition &IRP = getIRPosition();
2343
2344 bool IsKnown;
2347 DepClassTy::OPTIONAL, IsKnown))
2348 return ChangeStatus::UNCHANGED;
2349
2350 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2351 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2352 Instruction *UserI = cast<Instruction>(U.getUser());
2353 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2354 if (CB->isBundleOperand(&U))
2355 return false;
2356 if (!CB->isArgOperand(&U))
2357 return true;
2358 unsigned ArgNo = CB->getArgOperandNo(&U);
2359
2360 bool IsKnown;
2362 A, this, IRPosition::callsite_argument(*CB, ArgNo),
2363 DepClassTy::REQUIRED, IsKnown);
2364 }
2365
2366 if (isa<GetElementPtrInst>(UserI) || isa<PHINode>(UserI) ||
2367 isa<SelectInst>(UserI)) {
2368 Follow = true;
2369 return true;
2370 }
2371 if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI))
2372 return true;
2373
2374 if (isa<ReturnInst>(UserI) && getIRPosition().isArgumentPosition())
2375 return true;
2376
2377 // Unknown user.
2378 return false;
2379 };
2380 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2381 return indicatePessimisticFixpoint();
2382
2383 return ChangeStatus::UNCHANGED;
2384 }
2385};
2386
2387/// NoFree attribute for a call site argument.
2388struct AANoFreeArgument final : AANoFreeFloating {
2389 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2390 : AANoFreeFloating(IRP, A) {}
2391
2392 /// See AbstractAttribute::trackStatistics()
2393 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
2394};
2395
2396/// NoFree attribute for call site arguments.
2397struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2398 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2399 : AANoFreeFloating(IRP, A) {}
2400
2401 /// See AbstractAttribute::updateImpl(...).
2402 ChangeStatus updateImpl(Attributor &A) override {
2403 // TODO: Once we have call site specific value information we can provide
2404 // call site specific liveness information and then it makes
2405 // sense to specialize attributes for call sites arguments instead of
2406 // redirecting requests to the callee argument.
2407 Argument *Arg = getAssociatedArgument();
2408 if (!Arg)
2409 return indicatePessimisticFixpoint();
2410 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2411 bool IsKnown;
2413 DepClassTy::REQUIRED, IsKnown))
2414 return ChangeStatus::UNCHANGED;
2415 return indicatePessimisticFixpoint();
2416 }
2417
2418 /// See AbstractAttribute::trackStatistics()
2419 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nofree) };
2420};
2421
2422/// NoFree attribute for function return value.
2423struct AANoFreeReturned final : AANoFreeFloating {
2424 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2425 : AANoFreeFloating(IRP, A) {
2426 llvm_unreachable("NoFree is not applicable to function returns!");
2427 }
2428
2429 /// See AbstractAttribute::initialize(...).
2430 void initialize(Attributor &A) override {
2431 llvm_unreachable("NoFree is not applicable to function returns!");
2432 }
2433
2434 /// See AbstractAttribute::updateImpl(...).
2435 ChangeStatus updateImpl(Attributor &A) override {
2436 llvm_unreachable("NoFree is not applicable to function returns!");
2437 }
2438
2439 /// See AbstractAttribute::trackStatistics()
2440 void trackStatistics() const override {}
2441};
2442
2443/// NoFree attribute deduction for a call site return value.
2444struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2445 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2446 : AANoFreeFloating(IRP, A) {}
2447
2448 ChangeStatus manifest(Attributor &A) override {
2449 return ChangeStatus::UNCHANGED;
2450 }
2451 /// See AbstractAttribute::trackStatistics()
2452 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
2453};
2454} // namespace
2455
2456/// ------------------------ NonNull Argument Attribute ------------------------
2457
2459 Attribute::AttrKind ImpliedAttributeKind,
2460 bool IgnoreSubsumingPositions) {
2462 AttrKinds.push_back(Attribute::NonNull);
2465 AttrKinds.push_back(Attribute::Dereferenceable);
2466 if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2467 return true;
2468
2469 DominatorTree *DT = nullptr;
2470 AssumptionCache *AC = nullptr;
2471 InformationCache &InfoCache = A.getInfoCache();
2472 if (const Function *Fn = IRP.getAnchorScope()) {
2473 if (!Fn->isDeclaration()) {
2476 }
2477 }
2478
2480 if (IRP.getPositionKind() != IRP_RETURNED) {
2481 Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});
2482 } else {
2483 bool UsedAssumedInformation = false;
2484 if (!A.checkForAllInstructions(
2485 [&](Instruction &I) {
2486 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2487 return true;
2488 },
2489 IRP.getAssociatedFunction(), nullptr, {Instruction::Ret},
2490 UsedAssumedInformation, false, /*CheckPotentiallyDead=*/true))
2491 return false;
2492 }
2493
2494 if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) {
2495 return !isKnownNonZero(
2496 VAC.getValue(),
2497 SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI()));
2498 }))
2499 return false;
2500
2501 A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
2502 Attribute::NonNull)});
2503 return true;
2504}
2505
2506namespace {
2507static int64_t getKnownNonNullAndDerefBytesForUse(
2508 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2509 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2510 TrackUse = false;
2511
2512 const Value *UseV = U->get();
2513 if (!UseV->getType()->isPointerTy())
2514 return 0;
2515
2516 // We need to follow common pointer manipulation uses to the accesses they
2517 // feed into. We can try to be smart to avoid looking through things we do not
2518 // like for now, e.g., non-inbounds GEPs.
2519 if (isa<CastInst>(I)) {
2520 TrackUse = true;
2521 return 0;
2522 }
2523
2525 TrackUse = true;
2526 return 0;
2527 }
2528
2529 Type *PtrTy = UseV->getType();
2530 const Function *F = I->getFunction();
2533 const DataLayout &DL = A.getInfoCache().getDL();
2534 if (const auto *CB = dyn_cast<CallBase>(I)) {
2535 if (CB->isBundleOperand(U)) {
2536 if (RetainedKnowledge RK = getKnowledgeFromUse(
2537 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2538 IsNonNull |=
2539 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2540 return RK.ArgValue;
2541 }
2542 return 0;
2543 }
2544
2545 if (CB->isCallee(U)) {
2546 IsNonNull |= !NullPointerIsDefined;
2547 return 0;
2548 }
2549
2550 unsigned ArgNo = CB->getArgOperandNo(U);
2551 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2552 // As long as we only use known information there is no need to track
2553 // dependences here.
2554 bool IsKnownNonNull;
2556 DepClassTy::NONE, IsKnownNonNull);
2557 IsNonNull |= IsKnownNonNull;
2558 auto *DerefAA =
2559 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2560 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2561 }
2562
2563 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2564 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2565 Loc->Size.isScalable() || I->isVolatile())
2566 return 0;
2567
2568 int64_t Offset;
2569 const Value *Base =
2570 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2571 if (Base && Base == &AssociatedValue) {
2572 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2573 IsNonNull |= !NullPointerIsDefined;
2574 return std::max(int64_t(0), DerefBytes);
2575 }
2576
2577 /// Corner case when an offset is 0.
2579 /*AllowNonInbounds*/ true);
2580 if (Base && Base == &AssociatedValue && Offset == 0) {
2581 int64_t DerefBytes = Loc->Size.getValue();
2582 IsNonNull |= !NullPointerIsDefined;
2583 return std::max(int64_t(0), DerefBytes);
2584 }
2585
2586 return 0;
2587}
2588
2589struct AANonNullImpl : AANonNull {
2590 AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}
2591
2592 /// See AbstractAttribute::initialize(...).
2593 void initialize(Attributor &A) override {
2594 Value &V = *getAssociatedValue().stripPointerCasts();
2595 if (isa<ConstantPointerNull>(V)) {
2596 indicatePessimisticFixpoint();
2597 return;
2598 }
2599
2600 if (Instruction *CtxI = getCtxI())
2601 followUsesInMBEC(*this, A, getState(), *CtxI);
2602 }
2603
2604 /// See followUsesInMBEC
2605 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2606 AANonNull::StateType &State) {
2607 bool IsNonNull = false;
2608 bool TrackUse = false;
2609 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2610 IsNonNull, TrackUse);
2611 State.setKnown(IsNonNull);
2612 return TrackUse;
2613 }
2614
2615 /// See AbstractAttribute::getAsStr().
2616 const std::string getAsStr(Attributor *A) const override {
2617 return getAssumed() ? "nonnull" : "may-null";
2618 }
2619};
2620
2621/// NonNull attribute for a floating value.
2622struct AANonNullFloating : public AANonNullImpl {
2623 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2624 : AANonNullImpl(IRP, A) {}
2625
2626 /// See AbstractAttribute::updateImpl(...).
2627 ChangeStatus updateImpl(Attributor &A) override {
2628 auto CheckIRP = [&](const IRPosition &IRP) {
2629 bool IsKnownNonNull;
2631 A, *this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2632 };
2633
2634 bool Stripped;
2635 bool UsedAssumedInformation = false;
2636 Value *AssociatedValue = &getAssociatedValue();
2638 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2639 AA::AnyScope, UsedAssumedInformation))
2640 Stripped = false;
2641 else
2642 Stripped =
2643 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
2644
2645 if (!Stripped) {
2646 bool IsKnown;
2647 if (auto *PHI = dyn_cast<PHINode>(AssociatedValue))
2648 if (llvm::all_of(PHI->incoming_values(), [&](Value *Op) {
2649 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2650 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2651 IsKnown);
2652 }))
2653 return ChangeStatus::UNCHANGED;
2654 if (auto *Select = dyn_cast<SelectInst>(AssociatedValue))
2656 A, this, IRPosition::value(*Select->getFalseValue()),
2657 DepClassTy::OPTIONAL, IsKnown) &&
2659 A, this, IRPosition::value(*Select->getTrueValue()),
2660 DepClassTy::OPTIONAL, IsKnown))
2661 return ChangeStatus::UNCHANGED;
2662
2663 // If we haven't stripped anything we might still be able to use a
2664 // different AA, but only if the IRP changes. Effectively when we
2665 // interpret this not as a call site value but as a floating/argument
2666 // value.
2667 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
2668 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2669 return indicatePessimisticFixpoint();
2670 return ChangeStatus::UNCHANGED;
2671 }
2672
2673 for (const auto &VAC : Values)
2674 if (!CheckIRP(IRPosition::value(*VAC.getValue())))
2675 return indicatePessimisticFixpoint();
2676
2677 return ChangeStatus::UNCHANGED;
2678 }
2679
2680 /// See AbstractAttribute::trackStatistics()
2681 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2682};
2683
2684/// NonNull attribute for function return value.
2685struct AANonNullReturned final
2686 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2687 false, AANonNull::IRAttributeKind, false> {
2688 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2689 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2690 false, Attribute::NonNull, false>(IRP, A) {
2691 }
2692
2693 /// See AbstractAttribute::getAsStr().
2694 const std::string getAsStr(Attributor *A) const override {
2695 return getAssumed() ? "nonnull" : "may-null";
2696 }
2697
2698 /// See AbstractAttribute::trackStatistics()
2699 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2700};
2701
2702/// NonNull attribute for function argument.
2703struct AANonNullArgument final
2704 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2705 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2706 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2707
2708 /// See AbstractAttribute::trackStatistics()
2709 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
2710};
2711
2712struct AANonNullCallSiteArgument final : AANonNullFloating {
2713 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2714 : AANonNullFloating(IRP, A) {}
2715
2716 /// See AbstractAttribute::trackStatistics()
2717 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
2718};
2719
2720/// NonNull attribute for a call site return position.
2721struct AANonNullCallSiteReturned final
2722 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2723 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2724 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP, A) {}
2725
2726 /// See AbstractAttribute::trackStatistics()
2727 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
2728};
2729} // namespace
2730
2731/// ------------------------ Must-Progress Attributes --------------------------
2732namespace {
2733struct AAMustProgressImpl : public AAMustProgress {
2734 AAMustProgressImpl(const IRPosition &IRP, Attributor &A)
2735 : AAMustProgress(IRP, A) {}
2736
2737 /// See AbstractAttribute::initialize(...).
2738 void initialize(Attributor &A) override {
2739 bool IsKnown;
2741 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2742 (void)IsKnown;
2743 }
2744
2745 /// See AbstractAttribute::getAsStr()
2746 const std::string getAsStr(Attributor *A) const override {
2747 return getAssumed() ? "mustprogress" : "may-not-progress";
2748 }
2749};
2750
2751struct AAMustProgressFunction final : AAMustProgressImpl {
2752 AAMustProgressFunction(const IRPosition &IRP, Attributor &A)
2753 : AAMustProgressImpl(IRP, A) {}
2754
2755 /// See AbstractAttribute::updateImpl(...).
2756 ChangeStatus updateImpl(Attributor &A) override {
2757 bool IsKnown;
2759 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2760 if (IsKnown)
2761 return indicateOptimisticFixpoint();
2762 return ChangeStatus::UNCHANGED;
2763 }
2764
2765 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2766 IRPosition IPos = IRPosition::callsite_function(*ACS.getInstruction());
2767 bool IsKnownMustProgress;
2769 A, this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2770 /* IgnoreSubsumingPositions */ true);
2771 };
2772
2773 bool AllCallSitesKnown = true;
2774 if (!A.checkForAllCallSites(CheckForMustProgress, *this,
2775 /* RequireAllCallSites */ true,
2776 AllCallSitesKnown))
2777 return indicatePessimisticFixpoint();
2778
2779 return ChangeStatus::UNCHANGED;
2780 }
2781
2782 /// See AbstractAttribute::trackStatistics()
2783 void trackStatistics() const override {
2784 STATS_DECLTRACK_FN_ATTR(mustprogress)
2785 }
2786};
2787
2788/// MustProgress attribute deduction for a call sites.
2789struct AAMustProgressCallSite final : AAMustProgressImpl {
2790 AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)
2791 : AAMustProgressImpl(IRP, A) {}
2792
2793 /// See AbstractAttribute::updateImpl(...).
2794 ChangeStatus updateImpl(Attributor &A) override {
2795 // TODO: Once we have call site specific value information we can provide
2796 // call site specific liveness information and then it makes
2797 // sense to specialize attributes for call sites arguments instead of
2798 // redirecting requests to the callee argument.
2799 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
2800 bool IsKnownMustProgress;
2802 A, this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2803 return indicatePessimisticFixpoint();
2804 return ChangeStatus::UNCHANGED;
2805 }
2806
2807 /// See AbstractAttribute::trackStatistics()
2808 void trackStatistics() const override {
2809 STATS_DECLTRACK_CS_ATTR(mustprogress);
2810 }
2811};
2812} // namespace
2813
2814/// ------------------------ No-Recurse Attributes ----------------------------
2815
2816namespace {
2817struct AANoRecurseImpl : public AANoRecurse {
2818 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2819
2820 /// See AbstractAttribute::initialize(...).
2821 void initialize(Attributor &A) override {
2822 bool IsKnown;
2824 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2825 (void)IsKnown;
2826 }
2827
2828 /// See AbstractAttribute::getAsStr()
2829 const std::string getAsStr(Attributor *A) const override {
2830 return getAssumed() ? "norecurse" : "may-recurse";
2831 }
2832};
2833
2834struct AANoRecurseFunction final : AANoRecurseImpl {
2835 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2836 : AANoRecurseImpl(IRP, A) {}
2837
2838 /// See AbstractAttribute::updateImpl(...).
2839 ChangeStatus updateImpl(Attributor &A) override {
2840
2841 // If all live call sites are known to be no-recurse, we are as well.
2842 auto CallSitePred = [&](AbstractCallSite ACS) {
2843 bool IsKnownNoRecurse;
2845 A, this,
2846 IRPosition::function(*ACS.getInstruction()->getFunction()),
2847 DepClassTy::NONE, IsKnownNoRecurse))
2848 return false;
2849 return IsKnownNoRecurse;
2850 };
2851 bool UsedAssumedInformation = false;
2852 if (A.checkForAllCallSites(CallSitePred, *this, true,
2853 UsedAssumedInformation)) {
2854 // If we know all call sites and all are known no-recurse, we are done.
2855 // If all known call sites, which might not be all that exist, are known
2856 // to be no-recurse, we are not done but we can continue to assume
2857 // no-recurse. If one of the call sites we have not visited will become
2858 // live, another update is triggered.
2859 if (!UsedAssumedInformation)
2860 indicateOptimisticFixpoint();
2861 return ChangeStatus::UNCHANGED;
2862 }
2863
2864 const AAInterFnReachability *EdgeReachability =
2865 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2866 DepClassTy::REQUIRED);
2867 if (EdgeReachability && EdgeReachability->canReach(A, *getAnchorScope()))
2868 return indicatePessimisticFixpoint();
2869 return ChangeStatus::UNCHANGED;
2870 }
2871
2872 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
2873};
2874
2875/// NoRecurse attribute deduction for a call sites.
2876struct AANoRecurseCallSite final
2877 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2878 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2879 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP, A) {}
2880
2881 /// See AbstractAttribute::trackStatistics()
2882 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
2883};
2884} // namespace
2885
2886/// ------------------------ No-Convergent Attribute --------------------------
2887
2888namespace {
2889struct AANonConvergentImpl : public AANonConvergent {
2890 AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
2891 : AANonConvergent(IRP, A) {}
2892
2893 /// See AbstractAttribute::getAsStr()
2894 const std::string getAsStr(Attributor *A) const override {
2895 return getAssumed() ? "non-convergent" : "may-be-convergent";
2896 }
2897};
2898
2899struct AANonConvergentFunction final : AANonConvergentImpl {
2900 AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
2901 : AANonConvergentImpl(IRP, A) {}
2902
2903 /// See AbstractAttribute::updateImpl(...).
2904 ChangeStatus updateImpl(Attributor &A) override {
2905 // If all function calls are known to not be convergent, we are not
2906 // convergent.
2907 auto CalleeIsNotConvergent = [&](Instruction &Inst) {
2908 CallBase &CB = cast<CallBase>(Inst);
2910 if (!Callee || Callee->isIntrinsic()) {
2911 return false;
2912 }
2913 if (Callee->isDeclaration()) {
2914 return !Callee->hasFnAttribute(Attribute::Convergent);
2915 }
2916 const auto *ConvergentAA = A.getAAFor<AANonConvergent>(
2917 *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);
2918 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2919 };
2920
2921 bool UsedAssumedInformation = false;
2922 if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,
2923 UsedAssumedInformation)) {
2924 return indicatePessimisticFixpoint();
2925 }
2926 return ChangeStatus::UNCHANGED;
2927 }
2928
2929 ChangeStatus manifest(Attributor &A) override {
2930 if (isKnownNotConvergent() &&
2931 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2932 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2933 return ChangeStatus::CHANGED;
2934 }
2935 return ChangeStatus::UNCHANGED;
2936 }
2937
2938 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }
2939};
2940} // namespace
2941
2942/// -------------------- Undefined-Behavior Attributes ------------------------
2943
2944namespace {
2945struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2946 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2947 : AAUndefinedBehavior(IRP, A) {}
2948
2949 /// See AbstractAttribute::updateImpl(...).
2950 // through a pointer (i.e. also branches etc.)
2951 ChangeStatus updateImpl(Attributor &A) override {
2952 const size_t UBPrevSize = KnownUBInsts.size();
2953 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2954
2955 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2956 // Lang ref now states volatile store is not UB, let's skip them.
2957 if (I.isVolatile() && I.mayWriteToMemory())
2958 return true;
2959
2960 // Skip instructions that are already saved.
2961 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2962 return true;
2963
2964 // If we reach here, we know we have an instruction
2965 // that accesses memory through a pointer operand,
2966 // for which getPointerOperand() should give it to us.
2967 Value *PtrOp =
2968 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
2969 assert(PtrOp &&
2970 "Expected pointer operand of memory accessing instruction");
2971
2972 // Either we stopped and the appropriate action was taken,
2973 // or we got back a simplified value to continue.
2974 std::optional<Value *> SimplifiedPtrOp =
2975 stopOnUndefOrAssumed(A, PtrOp, &I);
2976 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2977 return true;
2978 const Value *PtrOpVal = *SimplifiedPtrOp;
2979
2980 // A memory access through a pointer is considered UB
2981 // only if the pointer has constant null value.
2982 // TODO: Expand it to not only check constant values.
2983 if (!isa<ConstantPointerNull>(PtrOpVal)) {
2984 AssumedNoUBInsts.insert(&I);
2985 return true;
2986 }
2987 const Type *PtrTy = PtrOpVal->getType();
2988
2989 // Because we only consider instructions inside functions,
2990 // assume that a parent function exists.
2991 const Function *F = I.getFunction();
2992
2993 // A memory access using constant null pointer is only considered UB
2994 // if null pointer is _not_ defined for the target platform.
2996 AssumedNoUBInsts.insert(&I);
2997 else
2998 KnownUBInsts.insert(&I);
2999 return true;
3000 };
3001
3002 auto InspectBrInstForUB = [&](Instruction &I) {
3003 // A conditional branch instruction is considered UB if it has `undef`
3004 // condition.
3005
3006 // Skip instructions that are already saved.
3007 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3008 return true;
3009
3010 // We know we have a branch instruction.
3011 auto *BrInst = cast<BranchInst>(&I);
3012
3013 // Unconditional branches are never considered UB.
3014 if (BrInst->isUnconditional())
3015 return true;
3016
3017 // Either we stopped and the appropriate action was taken,
3018 // or we got back a simplified value to continue.
3019 std::optional<Value *> SimplifiedCond =
3020 stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);
3021 if (!SimplifiedCond || !*SimplifiedCond)
3022 return true;
3023 AssumedNoUBInsts.insert(&I);
3024 return true;
3025 };
3026
3027 auto InspectCallSiteForUB = [&](Instruction &I) {
3028 // Check whether a callsite always cause UB or not
3029
3030 // Skip instructions that are already saved.
3031 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3032 return true;
3033
3034 // Check nonnull and noundef argument attribute violation for each
3035 // callsite.
3036 CallBase &CB = cast<CallBase>(I);
3038 if (!Callee)
3039 return true;
3040 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3041 // If current argument is known to be simplified to null pointer and the
3042 // corresponding argument position is known to have nonnull attribute,
3043 // the argument is poison. Furthermore, if the argument is poison and
3044 // the position is known to have noundef attriubte, this callsite is
3045 // considered UB.
3046 if (idx >= Callee->arg_size())
3047 break;
3048 Value *ArgVal = CB.getArgOperand(idx);
3049 if (!ArgVal)
3050 continue;
3051 // Here, we handle three cases.
3052 // (1) Not having a value means it is dead. (we can replace the value
3053 // with undef)
3054 // (2) Simplified to undef. The argument violate noundef attriubte.
3055 // (3) Simplified to null pointer where known to be nonnull.
3056 // The argument is a poison value and violate noundef attribute.
3057 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3058 bool IsKnownNoUndef;
3060 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3061 if (!IsKnownNoUndef)
3062 continue;
3063 bool UsedAssumedInformation = false;
3064 std::optional<Value *> SimplifiedVal =
3065 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3066 UsedAssumedInformation, AA::Interprocedural);
3067 if (UsedAssumedInformation)
3068 continue;
3069 if (SimplifiedVal && !*SimplifiedVal)
3070 return true;
3071 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3072 KnownUBInsts.insert(&I);
3073 continue;
3074 }
3075 if (!ArgVal->getType()->isPointerTy() ||
3076 !isa<ConstantPointerNull>(**SimplifiedVal))
3077 continue;
3078 bool IsKnownNonNull;
3080 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3081 if (IsKnownNonNull)
3082 KnownUBInsts.insert(&I);
3083 }
3084 return true;
3085 };
3086
3087 auto InspectReturnInstForUB = [&](Instruction &I) {
3088 auto &RI = cast<ReturnInst>(I);
3089 // Either we stopped and the appropriate action was taken,
3090 // or we got back a simplified return value to continue.
3091 std::optional<Value *> SimplifiedRetValue =
3092 stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);
3093 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3094 return true;
3095
3096 // Check if a return instruction always cause UB or not
3097 // Note: It is guaranteed that the returned position of the anchor
3098 // scope has noundef attribute when this is called.
3099 // We also ensure the return position is not "assumed dead"
3100 // because the returned value was then potentially simplified to
3101 // `undef` in AAReturnedValues without removing the `noundef`
3102 // attribute yet.
3103
3104 // When the returned position has noundef attriubte, UB occurs in the
3105 // following cases.
3106 // (1) Returned value is known to be undef.
3107 // (2) The value is known to be a null pointer and the returned
3108 // position has nonnull attribute (because the returned value is
3109 // poison).
3110 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3111 bool IsKnownNonNull;
3113 A, this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE,
3114 IsKnownNonNull);
3115 if (IsKnownNonNull)
3116 KnownUBInsts.insert(&I);
3117 }
3118
3119 return true;
3120 };
3121
3122 bool UsedAssumedInformation = false;
3123 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3124 {Instruction::Load, Instruction::Store,
3125 Instruction::AtomicCmpXchg,
3126 Instruction::AtomicRMW},
3127 UsedAssumedInformation,
3128 /* CheckBBLivenessOnly */ true);
3129 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
3130 UsedAssumedInformation,
3131 /* CheckBBLivenessOnly */ true);
3132 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3133 UsedAssumedInformation);
3134
3135 // If the returned position of the anchor scope has noundef attriubte, check
3136 // all returned instructions.
3137 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3138 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3139 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3140 bool IsKnownNoUndef;
3142 A, this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3143 if (IsKnownNoUndef)
3144 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3145 {Instruction::Ret}, UsedAssumedInformation,
3146 /* CheckBBLivenessOnly */ true);
3147 }
3148 }
3149
3150 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3151 UBPrevSize != KnownUBInsts.size())
3152 return ChangeStatus::CHANGED;
3153 return ChangeStatus::UNCHANGED;
3154 }
3155
3156 bool isKnownToCauseUB(Instruction *I) const override {
3157 return KnownUBInsts.count(I);
3158 }
3159
3160 bool isAssumedToCauseUB(Instruction *I) const override {
3161 // In simple words, if an instruction is not in the assumed to _not_
3162 // cause UB, then it is assumed UB (that includes those
3163 // in the KnownUBInsts set). The rest is boilerplate
3164 // is to ensure that it is one of the instructions we test
3165 // for UB.
3166
3167 switch (I->getOpcode()) {
3168 case Instruction::Load:
3169 case Instruction::Store:
3170 case Instruction::AtomicCmpXchg:
3171 case Instruction::AtomicRMW:
3172 return !AssumedNoUBInsts.count(I);
3173 case Instruction::Br: {
3174 auto *BrInst = cast<BranchInst>(I);
3175 if (BrInst->isUnconditional())
3176 return false;
3177 return !AssumedNoUBInsts.count(I);
3178 } break;
3179 default:
3180 return false;
3181 }
3182 return false;
3183 }
3184
3185 ChangeStatus manifest(Attributor &A) override {
3186 if (KnownUBInsts.empty())
3187 return ChangeStatus::UNCHANGED;
3188 for (Instruction *I : KnownUBInsts)
3189 A.changeToUnreachableAfterManifest(I);
3190 return ChangeStatus::CHANGED;
3191 }
3192
3193 /// See AbstractAttribute::getAsStr()
3194 const std::string getAsStr(Attributor *A) const override {
3195 return getAssumed() ? "undefined-behavior" : "no-ub";
3196 }
3197
3198 /// Note: The correctness of this analysis depends on the fact that the
3199 /// following 2 sets will stop changing after some point.
3200 /// "Change" here means that their size changes.
3201 /// The size of each set is monotonically increasing
3202 /// (we only add items to them) and it is upper bounded by the number of
3203 /// instructions in the processed function (we can never save more
3204 /// elements in either set than this number). Hence, at some point,
3205 /// they will stop increasing.
3206 /// Consequently, at some point, both sets will have stopped
3207 /// changing, effectively making the analysis reach a fixpoint.
3208
3209 /// Note: These 2 sets are disjoint and an instruction can be considered
3210 /// one of 3 things:
3211 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3212 /// the KnownUBInsts set.
3213 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3214 /// has a reason to assume it).
3215 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3216 /// could not find a reason to assume or prove that it can cause UB,
3217 /// hence it assumes it doesn't. We have a set for these instructions
3218 /// so that we don't reprocess them in every update.
3219 /// Note however that instructions in this set may cause UB.
3220
3221protected:
3222 /// A set of all live instructions _known_ to cause UB.
3223 SmallPtrSet<Instruction *, 8> KnownUBInsts;
3224
3225private:
3226 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3227 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3228
3229 // Should be called on updates in which if we're processing an instruction
3230 // \p I that depends on a value \p V, one of the following has to happen:
3231 // - If the value is assumed, then stop.
3232 // - If the value is known but undef, then consider it UB.
3233 // - Otherwise, do specific processing with the simplified value.
3234 // We return std::nullopt in the first 2 cases to signify that an appropriate
3235 // action was taken and the caller should stop.
3236 // Otherwise, we return the simplified value that the caller should
3237 // use for specific processing.
3238 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3239 Instruction *I) {
3240 bool UsedAssumedInformation = false;
3241 std::optional<Value *> SimplifiedV =
3242 A.getAssumedSimplified(IRPosition::value(*V), *this,
3243 UsedAssumedInformation, AA::Interprocedural);
3244 if (!UsedAssumedInformation) {
3245 // Don't depend on assumed values.
3246 if (!SimplifiedV) {
3247 // If it is known (which we tested above) but it doesn't have a value,
3248 // then we can assume `undef` and hence the instruction is UB.
3249 KnownUBInsts.insert(I);
3250 return std::nullopt;
3251 }
3252 if (!*SimplifiedV)
3253 return nullptr;
3254 V = *SimplifiedV;
3255 }
3256 if (isa<UndefValue>(V)) {
3257 KnownUBInsts.insert(I);
3258 return std::nullopt;
3259 }
3260 return V;
3261 }
3262};
3263
3264struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3265 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3266 : AAUndefinedBehaviorImpl(IRP, A) {}
3267
3268 /// See AbstractAttribute::trackStatistics()
3269 void trackStatistics() const override {
3270 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3271 "Number of instructions known to have UB");
3272 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
3273 KnownUBInsts.size();
3274 }
3275};
3276} // namespace
3277
3278/// ------------------------ Will-Return Attributes ----------------------------
3279
3280namespace {
3281// Helper function that checks whether a function has any cycle which we don't
3282// know if it is bounded or not.
3283// Loops with maximum trip count are considered bounded, any other cycle not.
3284static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3285 ScalarEvolution *SE =
3286 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3287 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3288 // If either SCEV or LoopInfo is not available for the function then we assume
3289 // any cycle to be unbounded cycle.
3290 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3291 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3292 if (!SE || !LI) {
3293 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3294 if (SCCI.hasCycle())
3295 return true;
3296 return false;
3297 }
3298
3299 // If there's irreducible control, the function may contain non-loop cycles.
3301 return true;
3302
3303 // Any loop that does not have a max trip count is considered unbounded cycle.
3304 for (auto *L : LI->getLoopsInPreorder()) {
3305 if (!SE->getSmallConstantMaxTripCount(L))
3306 return true;
3307 }
3308 return false;
3309}
3310
3311struct AAWillReturnImpl : public AAWillReturn {
3312 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3313 : AAWillReturn(IRP, A) {}
3314
3315 /// See AbstractAttribute::initialize(...).
3316 void initialize(Attributor &A) override {
3317 bool IsKnown;
3319 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3320 (void)IsKnown;
3321 }
3322
3323 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3324 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3325 if (!A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3326 return false;
3327
3328 bool IsKnown;
3329 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3330 return IsKnown || !KnownOnly;
3331 return false;
3332 }
3333
3334 /// See AbstractAttribute::updateImpl(...).
3335 ChangeStatus updateImpl(Attributor &A) override {
3336 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3337 return ChangeStatus::UNCHANGED;
3338
3339 auto CheckForWillReturn = [&](Instruction &I) {
3341 bool IsKnown;
3343 A, this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3344 if (IsKnown)
3345 return true;
3346 } else {
3347 return false;
3348 }
3349 bool IsKnownNoRecurse;
3351 A, this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3352 };
3353
3354 bool UsedAssumedInformation = false;
3355 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3356 UsedAssumedInformation))
3357 return indicatePessimisticFixpoint();
3358
3359 return ChangeStatus::UNCHANGED;
3360 }
3361
3362 /// See AbstractAttribute::getAsStr()
3363 const std::string getAsStr(Attributor *A) const override {
3364 return getAssumed() ? "willreturn" : "may-noreturn";
3365 }
3366};
3367
3368struct AAWillReturnFunction final : AAWillReturnImpl {
3369 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3370 : AAWillReturnImpl(IRP, A) {}
3371
3372 /// See AbstractAttribute::initialize(...).
3373 void initialize(Attributor &A) override {
3374 AAWillReturnImpl::initialize(A);
3375
3376 Function *F = getAnchorScope();
3377 assert(F && "Did expect an anchor function");
3378 if (F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3379 indicatePessimisticFixpoint();
3380 }
3381
3382 /// See AbstractAttribute::trackStatistics()
3383 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
3384};
3385
3386/// WillReturn attribute deduction for a call sites.
3387struct AAWillReturnCallSite final
3388 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3389 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3390 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP, A) {}
3391
3392 /// See AbstractAttribute::updateImpl(...).
3393 ChangeStatus updateImpl(Attributor &A) override {
3394 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3395 return ChangeStatus::UNCHANGED;
3396
3397 return AACalleeToCallSite::updateImpl(A);
3398 }
3399
3400 /// See AbstractAttribute::trackStatistics()
3401 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
3402};
3403} // namespace
3404
3405/// -------------------AAIntraFnReachability Attribute--------------------------
3406
3407/// All information associated with a reachability query. This boilerplate code
3408/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3409/// different \p ToTy values.
3410template <typename ToTy> struct ReachabilityQueryInfo {
3411 enum class Reachable {
3414 };
3415
3416 /// Start here,
3417 const Instruction *From = nullptr;
3418 /// reach this place,
3419 const ToTy *To = nullptr;
3420 /// without going through any of these instructions,
3422 /// and remember if it worked:
3424
3425 /// Precomputed hash for this RQI.
3426 unsigned Hash = 0;
3427
3428 unsigned computeHashValue() const {
3429 assert(Hash == 0 && "Computed hash twice!");
3432 return const_cast<ReachabilityQueryInfo<ToTy> *>(this)->Hash =
3433 detail::combineHashValue(PairDMI ::getHashValue({From, To}),
3434 InstSetDMI::getHashValue(ExclusionSet));
3435 }
3436
3438 : From(From), To(To) {}
3439
3440 /// Constructor replacement to ensure unique and stable sets are used for the
3441 /// cache.
3443 const AA::InstExclusionSetTy *ES, bool MakeUnique)
3444 : From(&From), To(&To), ExclusionSet(ES) {
3445
3446 if (!ES || ES->empty()) {
3447 ExclusionSet = nullptr;
3448 } else if (MakeUnique) {
3449 ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3450 }
3451 }
3452
3455};
3456
3457namespace llvm {
3458template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3461
3464
3467 return &TombstoneKey;
3468 }
3469 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3470 return RQI->Hash ? RQI->Hash : RQI->computeHashValue();
3471 }
3472 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3473 const ReachabilityQueryInfo<ToTy> *RHS) {
3474 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3475 return false;
3476 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3477 }
3478};
3479
3480#define DefineKeys(ToTy) \
3481 template <> \
3482 ReachabilityQueryInfo<ToTy> \
3483 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey = \
3484 ReachabilityQueryInfo<ToTy>( \
3485 DenseMapInfo<const Instruction *>::getEmptyKey(), \
3486 DenseMapInfo<const ToTy *>::getEmptyKey()); \
3487 template <> \
3488 ReachabilityQueryInfo<ToTy> \
3489 DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey = \
3490 ReachabilityQueryInfo<ToTy>( \
3491 DenseMapInfo<const Instruction *>::getTombstoneKey(), \
3492 DenseMapInfo<const ToTy *>::getTombstoneKey());
3493
3495#undef DefineKeys
3496
3497} // namespace llvm
3498
3499namespace {
3500
3501template <typename BaseTy, typename ToTy>
3502struct CachedReachabilityAA : public BaseTy {
3503 using RQITy = ReachabilityQueryInfo<ToTy>;
3504
3505 CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}
3506
3507 /// See AbstractAttribute::isQueryAA.
3508 bool isQueryAA() const override { return true; }
3509
3510 /// See AbstractAttribute::updateImpl(...).
3511 ChangeStatus updateImpl(Attributor &A) override {
3512 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3513 for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3514 RQITy *RQI = QueryVector[u];
3515 if (RQI->Result == RQITy::Reachable::No &&
3516 isReachableImpl(A, *RQI, /*IsTemporaryRQI=*/false))
3517 Changed = ChangeStatus::CHANGED;
3518 }
3519 return Changed;
3520 }
3521
3522 virtual bool isReachableImpl(Attributor &A, RQITy &RQI,
3523 bool IsTemporaryRQI) = 0;
3524
3525 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3526 RQITy &RQI, bool UsedExclusionSet, bool IsTemporaryRQI) {
3527 RQI.Result = Result;
3528
3529 // Remove the temporary RQI from the cache.
3530 if (IsTemporaryRQI)
3531 QueryCache.erase(&RQI);
3532
3533 // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
3534 // 1) If it is reachable, it doesn't matter if we have an exclusion set for
3535 // this query. 2) We did not use the exclusion set, potentially because
3536 // there is none.
3537 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3538 RQITy PlainRQI(RQI.From, RQI.To);
3539 if (!QueryCache.count(&PlainRQI)) {
3540 RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
3541 RQIPtr->Result = Result;
3542 QueryVector.push_back(RQIPtr);
3543 QueryCache.insert(RQIPtr);
3544 }
3545 }
3546
3547 // Check if we need to insert a new permanent RQI with the exclusion set.
3548 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3549 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3550 "Did not expect empty set!");
3551 RQITy *RQIPtr = new (A.Allocator)
3552 RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
3553 assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");
3554 RQIPtr->Result = Result;
3555 assert(!QueryCache.count(RQIPtr));
3556 QueryVector.push_back(RQIPtr);
3557 QueryCache.insert(RQIPtr);
3558 }
3559
3560 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3561 A.registerForUpdate(*this);
3562 return Result == RQITy::Reachable::Yes;
3563 }
3564
3565 const std::string getAsStr(Attributor *A) const override {
3566 // TODO: Return the number of reachable queries.
3567 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3568 }
3569
3570 bool checkQueryCache(Attributor &A, RQITy &StackRQI,
3571 typename RQITy::Reachable &Result) {
3572 if (!this->getState().isValidState()) {
3573 Result = RQITy::Reachable::Yes;
3574 return true;
3575 }
3576
3577 // If we have an exclusion set we might be able to find our answer by
3578 // ignoring it first.
3579 if (StackRQI.ExclusionSet) {
3580 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3581 auto It = QueryCache.find(&PlainRQI);
3582 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3583 Result = RQITy::Reachable::No;
3584 return true;
3585 }
3586 }
3587
3588 auto It = QueryCache.find(&StackRQI);
3589 if (It != QueryCache.end()) {
3590 Result = (*It)->Result;
3591 return true;
3592 }
3593
3594 // Insert a temporary for recursive queries. We will replace it with a
3595 // permanent entry later.
3596 QueryCache.insert(&StackRQI);
3597 return false;
3598 }
3599
3600private:
3601 SmallVector<RQITy *> QueryVector;
3602 DenseSet<RQITy *> QueryCache;
3603};
3604
3605struct AAIntraFnReachabilityFunction final
3606 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3607 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3608 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3609 : Base(IRP, A) {
3610 DT = A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3611 *IRP.getAssociatedFunction());
3612 }
3613
3614 bool isAssumedReachable(
3615 Attributor &A, const Instruction &From, const Instruction &To,
3616 const AA::InstExclusionSetTy *ExclusionSet) const override {
3617 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3618 if (&From == &To)
3619 return true;
3620
3621 RQITy StackRQI(A, From, To, ExclusionSet, false);
3622 RQITy::Reachable Result;
3623 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
3624 return NonConstThis->isReachableImpl(A, StackRQI,
3625 /*IsTemporaryRQI=*/true);
3626 return Result == RQITy::Reachable::Yes;
3627 }
3628
3629 ChangeStatus updateImpl(Attributor &A) override {
3630 // We only depend on liveness. DeadEdges is all we care about, check if any
3631 // of them changed.
3632 auto *LivenessAA =
3633 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3634 if (LivenessAA &&
3635 llvm::all_of(DeadEdges,
3636 [&](const auto &DeadEdge) {
3637 return LivenessAA->isEdgeDead(DeadEdge.first,
3638 DeadEdge.second);
3639 }) &&
3640 llvm::all_of(DeadBlocks, [&](const BasicBlock *BB) {
3641 return LivenessAA->isAssumedDead(BB);
3642 })) {
3643 return ChangeStatus::UNCHANGED;
3644 }
3645 DeadEdges.clear();
3646 DeadBlocks.clear();
3647 return Base::updateImpl(A);
3648 }
3649
3650 bool isReachableImpl(Attributor &A, RQITy &RQI,
3651 bool IsTemporaryRQI) override {
3652 const Instruction *Origin = RQI.From;
3653 bool UsedExclusionSet = false;
3654
3655 auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
3656 const AA::InstExclusionSetTy *ExclusionSet) {
3657 const Instruction *IP = &From;
3658 while (IP && IP != &To) {
3659 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {
3660 UsedExclusionSet = true;
3661 break;
3662 }
3663 IP = IP->getNextNode();
3664 }
3665 return IP == &To;
3666 };
3667
3668 const BasicBlock *FromBB = RQI.From->getParent();
3669 const BasicBlock *ToBB = RQI.To->getParent();
3670 assert(FromBB->getParent() == ToBB->getParent() &&
3671 "Not an intra-procedural query!");
3672
3673 // Check intra-block reachability, however, other reaching paths are still
3674 // possible.
3675 if (FromBB == ToBB &&
3676 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3677 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3678 IsTemporaryRQI);
3679
3680 // Check if reaching the ToBB block is sufficient or if even that would not
3681 // ensure reaching the target. In the latter case we are done.
3682 if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
3683 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3684 IsTemporaryRQI);
3685
3686 const Function *Fn = FromBB->getParent();
3687 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3688 if (RQI.ExclusionSet)
3689 for (auto *I : *RQI.ExclusionSet)
3690 if (I->getFunction() == Fn)
3691 ExclusionBlocks.insert(I->getParent());
3692
3693 // Check if we make it out of the FromBB block at all.
3694 if (ExclusionBlocks.count(FromBB) &&
3695 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3696 RQI.ExclusionSet))
3697 return rememberResult(A, RQITy::Reachable::No, RQI, true, IsTemporaryRQI);
3698
3699 auto *LivenessAA =
3700 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3701 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3702 DeadBlocks.insert(ToBB);
3703 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3704 IsTemporaryRQI);
3705 }
3706
3707 SmallPtrSet<const BasicBlock *, 16> Visited;
3709 Worklist.push_back(FromBB);
3710
3711 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3712 while (!Worklist.empty()) {
3713 const BasicBlock *BB = Worklist.pop_back_val();
3714 if (!Visited.insert(BB).second)
3715 continue;
3716 for (const BasicBlock *SuccBB : successors(BB)) {
3717 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3718 LocalDeadEdges.insert({BB, SuccBB});
3719 continue;
3720 }
3721 // We checked before if we just need to reach the ToBB block.
3722 if (SuccBB == ToBB)
3723 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3724 IsTemporaryRQI);
3725 if (DT && ExclusionBlocks.empty() && DT->dominates(BB, ToBB))
3726 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3727 IsTemporaryRQI);
3728
3729 if (ExclusionBlocks.count(SuccBB)) {
3730 UsedExclusionSet = true;
3731 continue;
3732 }
3733 Worklist.push_back(SuccBB);
3734 }
3735 }
3736
3737 DeadEdges.insert_range(LocalDeadEdges);
3738 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3739 IsTemporaryRQI);
3740 }
3741
3742 /// See AbstractAttribute::trackStatistics()
3743 void trackStatistics() const override {}
3744
3745private:
3746 // Set of assumed dead blocks we used in the last query. If any changes we
3747 // update the state.
3748 DenseSet<const BasicBlock *> DeadBlocks;
3749
3750 // Set of assumed dead edges we used in the last query. If any changes we
3751 // update the state.
3752 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3753
3754 /// The dominator tree of the function to short-circuit reasoning.
3755 const DominatorTree *DT = nullptr;
3756};
3757} // namespace
3758
3759/// ------------------------ NoAlias Argument Attribute ------------------------
3760
3762 Attribute::AttrKind ImpliedAttributeKind,
3763 bool IgnoreSubsumingPositions) {
3764 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3765 "Unexpected attribute kind");
3766 Value *Val = &IRP.getAssociatedValue();
3768 if (isa<AllocaInst>(Val))
3769 return true;
3770 } else {
3771 IgnoreSubsumingPositions = true;
3772 }
3773
3774 if (isa<UndefValue>(Val))
3775 return true;
3776
3777 if (isa<ConstantPointerNull>(Val) &&
3780 return true;
3781
3782 if (A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3783 IgnoreSubsumingPositions, Attribute::NoAlias))
3784 return true;
3785
3786 return false;
3787}
3788
3789namespace {
3790struct AANoAliasImpl : AANoAlias {
3791 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3792 assert(getAssociatedType()->isPointerTy() &&
3793 "Noalias is a pointer attribute");
3794 }
3795
3796 const std::string getAsStr(Attributor *A) const override {
3797 return getAssumed() ? "noalias" : "may-alias";
3798 }
3799};
3800
3801/// NoAlias attribute for a floating value.
3802struct AANoAliasFloating final : AANoAliasImpl {
3803 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3804 : AANoAliasImpl(IRP, A) {}
3805
3806 /// See AbstractAttribute::updateImpl(...).
3807 ChangeStatus updateImpl(Attributor &A) override {
3808 // TODO: Implement this.
3809 return indicatePessimisticFixpoint();
3810 }
3811
3812 /// See AbstractAttribute::trackStatistics()
3813 void trackStatistics() const override {
3815 }
3816};
3817
3818/// NoAlias attribute for an argument.
3819struct AANoAliasArgument final
3820 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3821 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3822 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3823
3824 /// See AbstractAttribute::update(...).
3825 ChangeStatus updateImpl(Attributor &A) override {
3826 // We have to make sure no-alias on the argument does not break
3827 // synchronization when this is a callback argument, see also [1] below.
3828 // If synchronization cannot be affected, we delegate to the base updateImpl
3829 // function, otherwise we give up for now.
3830
3831 // If the function is no-sync, no-alias cannot break synchronization.
3832 bool IsKnownNoSycn;
3834 A, this, IRPosition::function_scope(getIRPosition()),
3835 DepClassTy::OPTIONAL, IsKnownNoSycn))
3836 return Base::updateImpl(A);
3837
3838 // If the argument is read-only, no-alias cannot break synchronization.
3839 bool IsKnown;
3840 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3841 return Base::updateImpl(A);
3842
3843 // If the argument is never passed through callbacks, no-alias cannot break
3844 // synchronization.
3845 bool UsedAssumedInformation = false;
3846 if (A.checkForAllCallSites(
3847 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3848 true, UsedAssumedInformation))
3849 return Base::updateImpl(A);
3850
3851 // TODO: add no-alias but make sure it doesn't break synchronization by
3852 // introducing fake uses. See:
3853 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3854 // International Workshop on OpenMP 2018,
3855 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3856
3857 return indicatePessimisticFixpoint();
3858 }
3859
3860 /// See AbstractAttribute::trackStatistics()
3861 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
3862};
3863
3864struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3865 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3866 : AANoAliasImpl(IRP, A) {}
3867
3868 /// Determine if the underlying value may alias with the call site argument
3869 /// \p OtherArgNo of \p ICS (= the underlying call site).
3870 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3871 const AAMemoryBehavior &MemBehaviorAA,
3872 const CallBase &CB, unsigned OtherArgNo) {
3873 // We do not need to worry about aliasing with the underlying IRP.
3874 if (this->getCalleeArgNo() == (int)OtherArgNo)
3875 return false;
3876
3877 // If it is not a pointer or pointer vector we do not alias.
3878 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3879 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3880 return false;
3881
3882 auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3883 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3884
3885 // If the argument is readnone, there is no read-write aliasing.
3886 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3887 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3888 return false;
3889 }
3890
3891 // If the argument is readonly and the underlying value is readonly, there
3892 // is no read-write aliasing.
3893 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3894 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3895 IsReadOnly) {
3896 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3897 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3898 return false;
3899 }
3900
3901 // We have to utilize actual alias analysis queries so we need the object.
3902 if (!AAR)
3903 AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3904 *getAnchorScope());
3905
3906 // Try to rule it out at the call site.
3907 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3908 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
3909 "callsite arguments: "
3910 << getAssociatedValue() << " " << *ArgOp << " => "
3911 << (IsAliasing ? "" : "no-") << "alias \n");
3912
3913 return IsAliasing;
3914 }
3915
3916 bool isKnownNoAliasDueToNoAliasPreservation(
3917 Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {
3918 // We can deduce "noalias" if the following conditions hold.
3919 // (i) Associated value is assumed to be noalias in the definition.
3920 // (ii) Associated value is assumed to be no-capture in all the uses
3921 // possibly executed before this callsite.
3922 // (iii) There is no other pointer argument which could alias with the
3923 // value.
3924
3925 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3926 const Function *ScopeFn = VIRP.getAnchorScope();
3927 // Check whether the value is captured in the scope using AANoCapture.
3928 // Look at CFG and check only uses possibly executed before this
3929 // callsite.
3930 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3931 Instruction *UserI = cast<Instruction>(U.getUser());
3932
3933 // If UserI is the curr instruction and there is a single potential use of
3934 // the value in UserI we allow the use.
3935 // TODO: We should inspect the operands and allow those that cannot alias
3936 // with the value.
3937 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3938 return true;
3939
3940 if (ScopeFn) {
3941 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3942 if (CB->isArgOperand(&U)) {
3943
3944 unsigned ArgNo = CB->getArgOperandNo(&U);
3945
3946 bool IsKnownNoCapture;
3948 A, this, IRPosition::callsite_argument(*CB, ArgNo),
3949 DepClassTy::OPTIONAL, IsKnownNoCapture))
3950 return true;
3951 }
3952 }
3953
3955 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
3956 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3957 return true;
3958 }
3959
3960 // TODO: We should track the capturing uses in AANoCapture but the problem
3961 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3962 // a value in the module slice.
3963 // TODO(captures): Make this more precise.
3964 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
3965 if (capturesNothing(CI))
3966 return true;
3967 if (CI.isPassthrough()) {
3968 Follow = true;
3969 return true;
3970 }
3971 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI << "\n");
3972 return false;
3973 };
3974
3975 bool IsKnownNoCapture;
3976 const AANoCapture *NoCaptureAA = nullptr;
3977 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
3978 A, this, VIRP, DepClassTy::NONE, IsKnownNoCapture, false, &NoCaptureAA);
3979 if (!IsAssumedNoCapture &&
3980 (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
3981 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
3982 LLVM_DEBUG(
3983 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
3984 << " cannot be noalias as it is potentially captured\n");
3985 return false;
3986 }
3987 }
3988 if (NoCaptureAA)
3989 A.recordDependence(*NoCaptureAA, *this, DepClassTy::OPTIONAL);
3990
3991 // Check there is no other pointer argument which could alias with the
3992 // value passed at this call site.
3993 // TODO: AbstractCallSite
3994 const auto &CB = cast<CallBase>(getAnchorValue());
3995 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
3996 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
3997 return false;
3998
3999 return true;
4000 }
4001
4002 /// See AbstractAttribute::updateImpl(...).
4003 ChangeStatus updateImpl(Attributor &A) override {
4004 // If the argument is readnone we are done as there are no accesses via the
4005 // argument.
4006 auto *MemBehaviorAA =
4007 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
4008 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
4009 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
4010 return ChangeStatus::UNCHANGED;
4011 }
4012
4013 bool IsKnownNoAlias;
4014 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
4016 A, this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4017 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
4018 << " is not no-alias at the definition\n");
4019 return indicatePessimisticFixpoint();
4020 }
4021
4022 AAResults *AAR = nullptr;
4023 if (MemBehaviorAA &&
4024 isKnownNoAliasDueToNoAliasPreservation(A, AAR, *MemBehaviorAA)) {
4025 LLVM_DEBUG(
4026 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
4027 return ChangeStatus::UNCHANGED;
4028 }
4029
4030 return indicatePessimisticFixpoint();
4031 }
4032
4033 /// See AbstractAttribute::trackStatistics()
4034 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
4035};
4036
4037/// NoAlias attribute for function return value.
4038struct AANoAliasReturned final : AANoAliasImpl {
4039 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
4040 : AANoAliasImpl(IRP, A) {}
4041
4042 /// See AbstractAttribute::updateImpl(...).
4043 ChangeStatus updateImpl(Attributor &A) override {
4044
4045 auto CheckReturnValue = [&](Value &RV) -> bool {
4046 if (Constant *C = dyn_cast<Constant>(&RV))
4047 if (C->isNullValue() || isa<UndefValue>(C))
4048 return true;
4049
4050 /// For now, we can only deduce noalias if we have call sites.
4051 /// FIXME: add more support.
4052 if (!isa<CallBase>(&RV))
4053 return false;
4054
4055 const IRPosition &RVPos = IRPosition::value(RV);
4056 bool IsKnownNoAlias;
4058 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4059 return false;
4060
4061 bool IsKnownNoCapture;
4062 const AANoCapture *NoCaptureAA = nullptr;
4063 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
4064 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
4065 &NoCaptureAA);
4066 return IsAssumedNoCapture ||
4067 (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());
4068 };
4069
4070 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
4071 return indicatePessimisticFixpoint();
4072
4073 return ChangeStatus::UNCHANGED;
4074 }
4075
4076 /// See AbstractAttribute::trackStatistics()
4077 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
4078};
4079
4080/// NoAlias attribute deduction for a call site return value.
4081struct AANoAliasCallSiteReturned final
4082 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4083 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4084 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP, A) {}
4085
4086 /// See AbstractAttribute::trackStatistics()
4087 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
4088};
4089} // namespace
4090
4091/// -------------------AAIsDead Function Attribute-----------------------
4092
4093namespace {
4094struct AAIsDeadValueImpl : public AAIsDead {
4095 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4096
4097 /// See AAIsDead::isAssumedDead().
4098 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4099
4100 /// See AAIsDead::isKnownDead().
4101 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4102
4103 /// See AAIsDead::isAssumedDead(BasicBlock *).
4104 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4105
4106 /// See AAIsDead::isKnownDead(BasicBlock *).
4107 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4108
4109 /// See AAIsDead::isAssumedDead(Instruction *I).
4110 bool isAssumedDead(const Instruction *I) const override {
4111 return I == getCtxI() && isAssumedDead();
4112 }
4113
4114 /// See AAIsDead::isKnownDead(Instruction *I).
4115 bool isKnownDead(const Instruction *I) const override {
4116 return isAssumedDead(I) && isKnownDead();
4117 }
4118
4119 /// See AbstractAttribute::getAsStr().
4120 const std::string getAsStr(Attributor *A) const override {
4121 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4122 }
4123
4124 /// Check if all uses are assumed dead.
4125 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4126 // Callers might not check the type, void has no uses.
4127 if (V.getType()->isVoidTy() || V.use_empty())
4128 return true;
4129
4130 // If we replace a value with a constant there are no uses left afterwards.
4131 if (!isa<Constant>(V)) {
4132 if (auto *I = dyn_cast<Instruction>(&V))
4133 if (!A.isRunOn(*I->getFunction()))
4134 return false;
4135 bool UsedAssumedInformation = false;
4136 std::optional<Constant *> C =
4137 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4138 if (!C || *C)
4139 return true;
4140 }
4141
4142 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4143 // Explicitly set the dependence class to required because we want a long
4144 // chain of N dependent instructions to be considered live as soon as one is
4145 // without going through N update cycles. This is not required for
4146 // correctness.
4147 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4148 DepClassTy::REQUIRED,
4149 /* IgnoreDroppableUses */ false);
4150 }
4151
4152 /// Determine if \p I is assumed to be side-effect free.
4153 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4155 return true;
4156
4157 auto *CB = dyn_cast<CallBase>(I);
4158 if (!CB || isa<IntrinsicInst>(CB))
4159 return false;
4160
4161 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4162
4163 bool IsKnownNoUnwind;
4165 A, this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4166 return false;
4167
4168 bool IsKnown;
4169 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4170 }
4171};
4172
4173struct AAIsDeadFloating : public AAIsDeadValueImpl {
4174 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4175 : AAIsDeadValueImpl(IRP, A) {}
4176
4177 /// See AbstractAttribute::initialize(...).
4178 void initialize(Attributor &A) override {
4179 AAIsDeadValueImpl::initialize(A);
4180
4181 if (isa<UndefValue>(getAssociatedValue())) {
4182 indicatePessimisticFixpoint();
4183 return;
4184 }
4185
4186 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4187 if (!isAssumedSideEffectFree(A, I)) {
4189 indicatePessimisticFixpoint();
4190 else
4191 removeAssumedBits(HAS_NO_EFFECT);
4192 }
4193 }
4194
4195 bool isDeadFence(Attributor &A, FenceInst &FI) {
4196 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
4197 IRPosition::function(*FI.getFunction()), *this, DepClassTy::NONE);
4198 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4199 return false;
4200 A.recordDependence(*ExecDomainAA, *this, DepClassTy::OPTIONAL);
4201 return true;
4202 }
4203
4204 bool isDeadStore(Attributor &A, StoreInst &SI,
4205 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4206 // Lang ref now states volatile store is not UB/dead, let's skip them.
4207 if (SI.isVolatile())
4208 return false;
4209
4210 // If we are collecting assumes to be deleted we are in the manifest stage.
4211 // It's problematic to collect the potential copies again now so we use the
4212 // cached ones.
4213 bool UsedAssumedInformation = false;
4214 if (!AssumeOnlyInst) {
4215 PotentialCopies.clear();
4216 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4217 UsedAssumedInformation)) {
4218 LLVM_DEBUG(
4219 dbgs()
4220 << "[AAIsDead] Could not determine potential copies of store!\n");
4221 return false;
4222 }
4223 }
4224 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
4225 << " potential copies.\n");
4226
4227 InformationCache &InfoCache = A.getInfoCache();
4228 return llvm::all_of(PotentialCopies, [&](Value *V) {
4229 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4230 UsedAssumedInformation))
4231 return true;
4232 if (auto *LI = dyn_cast<LoadInst>(V)) {
4233 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4234 auto &UserI = cast<Instruction>(*U.getUser());
4235 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4236 if (AssumeOnlyInst)
4237 AssumeOnlyInst->insert(&UserI);
4238 return true;
4239 }
4240 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4241 })) {
4242 return true;
4243 }
4244 }
4245 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
4246 << " is assumed live!\n");
4247 return false;
4248 });
4249 }
4250
4251 /// See AbstractAttribute::getAsStr().
4252 const std::string getAsStr(Attributor *A) const override {
4253 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4255 if (isValidState())
4256 return "assumed-dead-store";
4258 if (isValidState())
4259 return "assumed-dead-fence";
4260 return AAIsDeadValueImpl::getAsStr(A);
4261 }
4262
4263 /// See AbstractAttribute::updateImpl(...).
4264 ChangeStatus updateImpl(Attributor &A) override {
4265 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4266 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4267 if (!isDeadStore(A, *SI))
4268 return indicatePessimisticFixpoint();
4269 } else if (auto *FI = dyn_cast_or_null<FenceInst>(I)) {
4270 if (!isDeadFence(A, *FI))
4271 return indicatePessimisticFixpoint();
4272 } else {
4273 if (!isAssumedSideEffectFree(A, I))
4274 return indicatePessimisticFixpoint();
4275 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4276 return indicatePessimisticFixpoint();
4277 }
4279 }
4280
4281 bool isRemovableStore() const override {
4282 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4283 }
4284
4285 /// See AbstractAttribute::manifest(...).
4286 ChangeStatus manifest(Attributor &A) override {
4287 Value &V = getAssociatedValue();
4288 if (auto *I = dyn_cast<Instruction>(&V)) {
4289 // If we get here we basically know the users are all dead. We check if
4290 // isAssumedSideEffectFree returns true here again because it might not be
4291 // the case and only the users are dead but the instruction (=call) is
4292 // still needed.
4293 if (auto *SI = dyn_cast<StoreInst>(I)) {
4294 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4295 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4296 (void)IsDead;
4297 assert(IsDead && "Store was assumed to be dead!");
4298 A.deleteAfterManifest(*I);
4299 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4300 Instruction *AOI = AssumeOnlyInst[i];
4301 for (auto *Usr : AOI->users())
4302 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4303 A.deleteAfterManifest(*AOI);
4304 }
4305 return ChangeStatus::CHANGED;
4306 }
4307 if (auto *FI = dyn_cast<FenceInst>(I)) {
4308 assert(isDeadFence(A, *FI));
4309 A.deleteAfterManifest(*FI);
4310 return ChangeStatus::CHANGED;
4311 }
4312 if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {
4313 A.deleteAfterManifest(*I);
4314 return ChangeStatus::CHANGED;
4315 }
4316 }
4318 }
4319
4320 /// See AbstractAttribute::trackStatistics()
4321 void trackStatistics() const override {
4323 }
4324
4325private:
4326 // The potential copies of a dead store, used for deletion during manifest.
4327 SmallSetVector<Value *, 4> PotentialCopies;
4328};
4329
4330struct AAIsDeadArgument : public AAIsDeadFloating {
4331 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4332 : AAIsDeadFloating(IRP, A) {}
4333
4334 /// See AbstractAttribute::manifest(...).
4335 ChangeStatus manifest(Attributor &A) override {
4336 Argument &Arg = *getAssociatedArgument();
4337 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4338 if (A.registerFunctionSignatureRewrite(
4339 Arg, /* ReplacementTypes */ {},
4342 return ChangeStatus::CHANGED;
4343 }
4344 return ChangeStatus::UNCHANGED;
4345 }
4346
4347 /// See AbstractAttribute::trackStatistics()
4348 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
4349};
4350
4351struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4352 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4353 : AAIsDeadValueImpl(IRP, A) {}
4354
4355 /// See AbstractAttribute::initialize(...).
4356 void initialize(Attributor &A) override {
4357 AAIsDeadValueImpl::initialize(A);
4358 if (isa<UndefValue>(getAssociatedValue()))
4359 indicatePessimisticFixpoint();
4360 }
4361
4362 /// See AbstractAttribute::updateImpl(...).
4363 ChangeStatus updateImpl(Attributor &A) override {
4364 // TODO: Once we have call site specific value information we can provide
4365 // call site specific liveness information and then it makes
4366 // sense to specialize attributes for call sites arguments instead of
4367 // redirecting requests to the callee argument.
4368 Argument *Arg = getAssociatedArgument();
4369 if (!Arg)
4370 return indicatePessimisticFixpoint();
4371 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4372 auto *ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4373 if (!ArgAA)
4374 return indicatePessimisticFixpoint();
4375 return clampStateAndIndicateChange(getState(), ArgAA->getState());
4376 }
4377
4378 /// See AbstractAttribute::manifest(...).
4379 ChangeStatus manifest(Attributor &A) override {
4380 CallBase &CB = cast<CallBase>(getAnchorValue());
4381 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4382 assert(!isa<UndefValue>(U.get()) &&
4383 "Expected undef values to be filtered out!");
4384 UndefValue &UV = *UndefValue::get(U->getType());
4385 if (A.changeUseAfterManifest(U, UV))
4386 return ChangeStatus::CHANGED;
4387 return ChangeStatus::UNCHANGED;
4388 }
4389
4390 /// See AbstractAttribute::trackStatistics()
4391 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
4392};
4393
4394struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4395 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4396 : AAIsDeadFloating(IRP, A) {}
4397
4398 /// See AAIsDead::isAssumedDead().
4399 bool isAssumedDead() const override {
4400 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4401 }
4402
4403 /// See AbstractAttribute::initialize(...).
4404 void initialize(Attributor &A) override {
4405 AAIsDeadFloating::initialize(A);
4406 if (isa<UndefValue>(getAssociatedValue())) {
4407 indicatePessimisticFixpoint();
4408 return;
4409 }
4410
4411 // We track this separately as a secondary state.
4412 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4413 }
4414
4415 /// See AbstractAttribute::updateImpl(...).
4416 ChangeStatus updateImpl(Attributor &A) override {
4417 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4418 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4419 IsAssumedSideEffectFree = false;
4420 Changed = ChangeStatus::CHANGED;
4421 }
4422 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4423 return indicatePessimisticFixpoint();
4424 return Changed;
4425 }
4426
4427 /// See AbstractAttribute::trackStatistics()
4428 void trackStatistics() const override {
4429 if (IsAssumedSideEffectFree)
4431 else
4432 STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
4433 }
4434
4435 /// See AbstractAttribute::getAsStr().
4436 const std::string getAsStr(Attributor *A) const override {
4437 return isAssumedDead()
4438 ? "assumed-dead"
4439 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4440 }
4441
4442private:
4443 bool IsAssumedSideEffectFree = true;
4444};
4445
4446struct AAIsDeadReturned : public AAIsDeadValueImpl {
4447 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4448 : AAIsDeadValueImpl(IRP, A) {}
4449
4450 /// See AbstractAttribute::updateImpl(...).
4451 ChangeStatus updateImpl(Attributor &A) override {
4452
4453 bool UsedAssumedInformation = false;
4454 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4455 {Instruction::Ret}, UsedAssumedInformation);
4456
4457 auto PredForCallSite = [&](AbstractCallSite ACS) {
4458 if (ACS.isCallbackCall() || !ACS.getInstruction())
4459 return false;
4460 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4461 };
4462
4463 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4464 UsedAssumedInformation))
4465 return indicatePessimisticFixpoint();
4466
4467 return ChangeStatus::UNCHANGED;
4468 }
4469
4470 /// See AbstractAttribute::manifest(...).
4471 ChangeStatus manifest(Attributor &A) override {
4472 // TODO: Rewrite the signature to return void?
4473 bool AnyChange = false;
4474 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4475 auto RetInstPred = [&](Instruction &I) {
4476 ReturnInst &RI = cast<ReturnInst>(I);
4478 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4479 return true;
4480 };
4481 bool UsedAssumedInformation = false;
4482 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4483 UsedAssumedInformation);
4484 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4485 }
4486
4487 /// See AbstractAttribute::trackStatistics()
4488 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
4489};
4490
4491struct AAIsDeadFunction : public AAIsDead {
4492 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4493
4494 /// See AbstractAttribute::initialize(...).
4495 void initialize(Attributor &A) override {
4496 Function *F = getAnchorScope();
4497 assert(F && "Did expect an anchor function");
4498 if (!isAssumedDeadInternalFunction(A)) {
4499 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4500 assumeLive(A, F->getEntryBlock());
4501 }
4502 }
4503
4504 bool isAssumedDeadInternalFunction(Attributor &A) {
4505 if (!getAnchorScope()->hasLocalLinkage())
4506 return false;
4507 bool UsedAssumedInformation = false;
4508 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4509 true, UsedAssumedInformation);
4510 }
4511
4512 /// See AbstractAttribute::getAsStr().
4513 const std::string getAsStr(Attributor *A) const override {
4514 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4515 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4516 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4517 std::to_string(KnownDeadEnds.size()) + "]";
4518 }
4519
4520 /// See AbstractAttribute::manifest(...).
4521 ChangeStatus manifest(Attributor &A) override {
4522 assert(getState().isValidState() &&
4523 "Attempted to manifest an invalid state!");
4524
4525 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4526 Function &F = *getAnchorScope();
4527
4528 if (AssumedLiveBlocks.empty()) {
4529 A.deleteAfterManifest(F);
4530 return ChangeStatus::CHANGED;
4531 }
4532
4533 // Flag to determine if we can change an invoke to a call assuming the
4534 // callee is nounwind. This is not possible if the personality of the
4535 // function allows to catch asynchronous exceptions.
4536 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4537
4538 KnownDeadEnds.set_union(ToBeExploredFrom);
4539 for (const Instruction *DeadEndI : KnownDeadEnds) {
4540 auto *CB = dyn_cast<CallBase>(DeadEndI);
4541 if (!CB)
4542 continue;
4543 bool IsKnownNoReturn;
4545 A, this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL,
4546 IsKnownNoReturn);
4547 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4548 continue;
4549
4550 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4551 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4552 else
4553 A.changeToUnreachableAfterManifest(
4554 const_cast<Instruction *>(DeadEndI->getNextNode()));
4555 HasChanged = ChangeStatus::CHANGED;
4556 }
4557
4558 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
4559 for (BasicBlock &BB : F)
4560 if (!AssumedLiveBlocks.count(&BB)) {
4561 A.deleteAfterManifest(BB);
4562 ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
4563 HasChanged = ChangeStatus::CHANGED;
4564 }
4565
4566 return HasChanged;
4567 }
4568
4569 /// See AbstractAttribute::updateImpl(...).
4570 ChangeStatus updateImpl(Attributor &A) override;
4571
4572 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4573 assert(From->getParent() == getAnchorScope() &&
4574 To->getParent() == getAnchorScope() &&
4575 "Used AAIsDead of the wrong function");
4576 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4577 }
4578
4579 /// See AbstractAttribute::trackStatistics()
4580 void trackStatistics() const override {}
4581
4582 /// Returns true if the function is assumed dead.
4583 bool isAssumedDead() const override { return false; }
4584
4585 /// See AAIsDead::isKnownDead().
4586 bool isKnownDead() const override { return false; }
4587
4588 /// See AAIsDead::isAssumedDead(BasicBlock *).
4589 bool isAssumedDead(const BasicBlock *BB) const override {
4590 assert(BB->getParent() == getAnchorScope() &&
4591 "BB must be in the same anchor scope function.");
4592
4593 if (!getAssumed())
4594 return false;
4595 return !AssumedLiveBlocks.count(BB);
4596 }
4597
4598 /// See AAIsDead::isKnownDead(BasicBlock *).
4599 bool isKnownDead(const BasicBlock *BB) const override {
4600 return getKnown() && isAssumedDead(BB);
4601 }
4602
4603 /// See AAIsDead::isAssumed(Instruction *I).
4604 bool isAssumedDead(const Instruction *I) const override {
4605 assert(I->getParent()->getParent() == getAnchorScope() &&
4606 "Instruction must be in the same anchor scope function.");
4607
4608 if (!getAssumed())
4609 return false;
4610
4611 // If it is not in AssumedLiveBlocks then it for sure dead.
4612 // Otherwise, it can still be after noreturn call in a live block.
4613 if (!AssumedLiveBlocks.count(I->getParent()))
4614 return true;
4615
4616 // If it is not after a liveness barrier it is live.
4617 const Instruction *PrevI = I->getPrevNode();
4618 while (PrevI) {
4619 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4620 return true;
4621 PrevI = PrevI->getPrevNode();
4622 }
4623 return false;
4624 }
4625
4626 /// See AAIsDead::isKnownDead(Instruction *I).
4627 bool isKnownDead(const Instruction *I) const override {
4628 return getKnown() && isAssumedDead(I);
4629 }
4630
4631 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4632 /// that internal function called from \p BB should now be looked at.
4633 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4634 if (!AssumedLiveBlocks.insert(&BB).second)
4635 return false;
4636
4637 // We assume that all of BB is (probably) live now and if there are calls to
4638 // internal functions we will assume that those are now live as well. This
4639 // is a performance optimization for blocks with calls to a lot of internal
4640 // functions. It can however cause dead functions to be treated as live.
4641 for (const Instruction &I : BB)
4642 if (const auto *CB = dyn_cast<CallBase>(&I))
4644 if (F->hasLocalLinkage())
4645 A.markLiveInternalFunction(*F);
4646 return true;
4647 }
4648
4649 /// Collection of instructions that need to be explored again, e.g., we
4650 /// did assume they do not transfer control to (one of their) successors.
4651 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4652
4653 /// Collection of instructions that are known to not transfer control.
4654 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4655
4656 /// Collection of all assumed live edges
4657 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4658
4659 /// Collection of all assumed live BasicBlocks.
4660 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4661};
4662
4663static bool
4664identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4665 AbstractAttribute &AA,
4666 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4667 const IRPosition &IPos = IRPosition::callsite_function(CB);
4668
4669 bool IsKnownNoReturn;
4671 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoReturn))
4672 return !IsKnownNoReturn;
4673 if (CB.isTerminator())
4674 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4675 else
4676 AliveSuccessors.push_back(CB.getNextNode());
4677 return false;
4678}
4679
4680static bool
4681identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4682 AbstractAttribute &AA,
4683 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4684 bool UsedAssumedInformation =
4685 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4686
4687 // First, determine if we can change an invoke to a call assuming the
4688 // callee is nounwind. This is not possible if the personality of the
4689 // function allows to catch asynchronous exceptions.
4690 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4691 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4692 } else {
4693 const IRPosition &IPos = IRPosition::callsite_function(II);
4694
4695 bool IsKnownNoUnwind;
4697 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
4698 UsedAssumedInformation |= !IsKnownNoUnwind;
4699 } else {
4700 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4701 }
4702 }
4703 return UsedAssumedInformation;
4704}
4705
4706static bool
4707identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
4708 AbstractAttribute &AA,
4709 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4710 bool UsedAssumedInformation = false;
4711 if (BI.getNumSuccessors() == 1) {
4712 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4713 } else {
4714 std::optional<Constant *> C =
4715 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4716 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4717 // No value yet, assume both edges are dead.
4718 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4719 const BasicBlock *SuccBB =
4720 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4721 AliveSuccessors.push_back(&SuccBB->front());
4722 } else {
4723 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4724 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4725 UsedAssumedInformation = false;
4726 }
4727 }
4728 return UsedAssumedInformation;
4729}
4730
4731static bool
4732identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4733 AbstractAttribute &AA,
4734 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4735 bool UsedAssumedInformation = false;
4737 if (!A.getAssumedSimplifiedValues(IRPosition::value(*SI.getCondition()), &AA,
4738 Values, AA::AnyScope,
4739 UsedAssumedInformation)) {
4740 // Something went wrong, assume all successors are live.
4741 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4742 AliveSuccessors.push_back(&SuccBB->front());
4743 return false;
4744 }
4745
4746 if (Values.empty() ||
4747 (Values.size() == 1 &&
4748 isa_and_nonnull<UndefValue>(Values.front().getValue()))) {
4749 // No valid value yet, assume all edges are dead.
4750 return UsedAssumedInformation;
4751 }
4752
4753 Type &Ty = *SI.getCondition()->getType();
4754 SmallPtrSet<ConstantInt *, 8> Constants;
4755 auto CheckForConstantInt = [&](Value *V) {
4756 if (auto *CI = dyn_cast_if_present<ConstantInt>(AA::getWithType(*V, Ty))) {
4757 Constants.insert(CI);
4758 return true;
4759 }
4760 return false;
4761 };
4762
4763 if (!all_of(Values, [&](AA::ValueAndContext &VAC) {
4764 return CheckForConstantInt(VAC.getValue());
4765 })) {
4766 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4767 AliveSuccessors.push_back(&SuccBB->front());
4768 return UsedAssumedInformation;
4769 }
4770
4771 unsigned MatchedCases = 0;
4772 for (const auto &CaseIt : SI.cases()) {
4773 if (Constants.count(CaseIt.getCaseValue())) {
4774 ++MatchedCases;
4775 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4776 }
4777 }
4778
4779 // If all potential values have been matched, we will not visit the default
4780 // case.
4781 if (MatchedCases < Constants.size())
4782 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4783 return UsedAssumedInformation;
4784}
4785
4786ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4788
4789 if (AssumedLiveBlocks.empty()) {
4790 if (isAssumedDeadInternalFunction(A))
4792
4793 Function *F = getAnchorScope();
4794 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4795 assumeLive(A, F->getEntryBlock());
4796 Change = ChangeStatus::CHANGED;
4797 }
4798
4799 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
4800 << getAnchorScope()->size() << "] BBs and "
4801 << ToBeExploredFrom.size() << " exploration points and "
4802 << KnownDeadEnds.size() << " known dead ends\n");
4803
4804 // Copy and clear the list of instructions we need to explore from. It is
4805 // refilled with instructions the next update has to look at.
4806 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4807 ToBeExploredFrom.end());
4808 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4809
4811 while (!Worklist.empty()) {
4812 const Instruction *I = Worklist.pop_back_val();
4813 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");
4814
4815 // Fast forward for uninteresting instructions. We could look for UB here
4816 // though.
4817 while (!I->isTerminator() && !isa<CallBase>(I))
4818 I = I->getNextNode();
4819
4820 AliveSuccessors.clear();
4821
4822 bool UsedAssumedInformation = false;
4823 switch (I->getOpcode()) {
4824 // TODO: look for (assumed) UB to backwards propagate "deadness".
4825 default:
4826 assert(I->isTerminator() &&
4827 "Expected non-terminators to be handled already!");
4828 for (const BasicBlock *SuccBB : successors(I->getParent()))
4829 AliveSuccessors.push_back(&SuccBB->front());
4830 break;
4831 case Instruction::Call:
4832 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4833 *this, AliveSuccessors);
4834 break;
4835 case Instruction::Invoke:
4836 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4837 *this, AliveSuccessors);
4838 break;
4839 case Instruction::Br:
4840 UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),
4841 *this, AliveSuccessors);
4842 break;
4843 case Instruction::Switch:
4844 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4845 *this, AliveSuccessors);
4846 break;
4847 }
4848
4849 if (UsedAssumedInformation) {
4850 NewToBeExploredFrom.insert(I);
4851 } else if (AliveSuccessors.empty() ||
4852 (I->isTerminator() &&
4853 AliveSuccessors.size() < I->getNumSuccessors())) {
4854 if (KnownDeadEnds.insert(I))
4855 Change = ChangeStatus::CHANGED;
4856 }
4857
4858 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
4859 << AliveSuccessors.size() << " UsedAssumedInformation: "
4860 << UsedAssumedInformation << "\n");
4861
4862 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4863 if (!I->isTerminator()) {
4864 assert(AliveSuccessors.size() == 1 &&
4865 "Non-terminator expected to have a single successor!");
4866 Worklist.push_back(AliveSuccessor);
4867 } else {
4868 // record the assumed live edge
4869 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4870 if (AssumedLiveEdges.insert(Edge).second)
4871 Change = ChangeStatus::CHANGED;
4872 if (assumeLive(A, *AliveSuccessor->getParent()))
4873 Worklist.push_back(AliveSuccessor);
4874 }
4875 }
4876 }
4877
4878 // Check if the content of ToBeExploredFrom changed, ignore the order.
4879 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4880 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4881 return !ToBeExploredFrom.count(I);
4882 })) {
4883 Change = ChangeStatus::CHANGED;
4884 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4885 }
4886
4887 // If we know everything is live there is no need to query for liveness.
4888 // Instead, indicating a pessimistic fixpoint will cause the state to be
4889 // "invalid" and all queries to be answered conservatively without lookups.
4890 // To be in this state we have to (1) finished the exploration and (3) not
4891 // discovered any non-trivial dead end and (2) not ruled unreachable code
4892 // dead.
4893 if (ToBeExploredFrom.empty() &&
4894 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4895 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4896 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4897 }))
4898 return indicatePessimisticFixpoint();
4899 return Change;
4900}
4901
4902/// Liveness information for a call sites.
4903struct AAIsDeadCallSite final : AAIsDeadFunction {
4904 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4905 : AAIsDeadFunction(IRP, A) {}
4906
4907 /// See AbstractAttribute::initialize(...).
4908 void initialize(Attributor &A) override {
4909 // TODO: Once we have call site specific value information we can provide
4910 // call site specific liveness information and then it makes
4911 // sense to specialize attributes for call sites instead of
4912 // redirecting requests to the callee.
4913 llvm_unreachable("Abstract attributes for liveness are not "
4914 "supported for call sites yet!");
4915 }
4916
4917 /// See AbstractAttribute::updateImpl(...).
4918 ChangeStatus updateImpl(Attributor &A) override {
4919 return indicatePessimisticFixpoint();
4920 }
4921
4922 /// See AbstractAttribute::trackStatistics()
4923 void trackStatistics() const override {}
4924};
4925} // namespace
4926
4927/// -------------------- Dereferenceable Argument Attribute --------------------
4928
4929namespace {
4930struct AADereferenceableImpl : AADereferenceable {
4931 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4932 : AADereferenceable(IRP, A) {}
4933 using StateType = DerefState;
4934
4935 /// See AbstractAttribute::initialize(...).
4936 void initialize(Attributor &A) override {
4937 Value &V = *getAssociatedValue().stripPointerCasts();
4939 A.getAttrs(getIRPosition(),
4940 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
4941 Attrs, /* IgnoreSubsumingPositions */ false);
4942 for (const Attribute &Attr : Attrs)
4943 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
4944
4945 // Ensure we initialize the non-null AA (if necessary).
4946 bool IsKnownNonNull;
4948 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
4949
4950 bool CanBeNull, CanBeFreed;
4951 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
4952 A.getDataLayout(), CanBeNull, CanBeFreed));
4953
4954 if (Instruction *CtxI = getCtxI())
4955 followUsesInMBEC(*this, A, getState(), *CtxI);
4956 }
4957
4958 /// See AbstractAttribute::getState()
4959 /// {
4960 StateType &getState() override { return *this; }
4961 const StateType &getState() const override { return *this; }
4962 /// }
4963
4964 /// Helper function for collecting accessed bytes in must-be-executed-context
4965 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
4966 DerefState &State) {
4967 const Value *UseV = U->get();
4968 if (!UseV->getType()->isPointerTy())
4969 return;
4970
4971 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
4972 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
4973 return;
4974
4975 int64_t Offset;
4977 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
4978 if (Base && Base == &getAssociatedValue())
4979 State.addAccessedBytes(Offset, Loc->Size.getValue());
4980 }
4981
4982 /// See followUsesInMBEC
4983 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
4984 AADereferenceable::StateType &State) {
4985 bool IsNonNull = false;
4986 bool TrackUse = false;
4987 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
4988 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
4989 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
4990 << " for instruction " << *I << "\n");
4991
4992 addAccessedBytesForUse(A, U, I, State);
4993 State.takeKnownDerefBytesMaximum(DerefBytes);
4994 return TrackUse;
4995 }
4996
4997 /// See AbstractAttribute::manifest(...).
4998 ChangeStatus manifest(Attributor &A) override {
4999 ChangeStatus Change = AADereferenceable::manifest(A);
5000 bool IsKnownNonNull;
5001 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5002 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5003 if (IsAssumedNonNull &&
5004 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5005 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5006 return ChangeStatus::CHANGED;
5007 }
5008 return Change;
5009 }
5010
5011 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5012 SmallVectorImpl<Attribute> &Attrs) const override {
5013 // TODO: Add *_globally support
5014 bool IsKnownNonNull;
5015 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5016 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5017 if (IsAssumedNonNull)
5018 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5019 Ctx, getAssumedDereferenceableBytes()));
5020 else
5021 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5022 Ctx, getAssumedDereferenceableBytes()));
5023 }
5024
5025 /// See AbstractAttribute::getAsStr().
5026 const std::string getAsStr(Attributor *A) const override {
5027 if (!getAssumedDereferenceableBytes())
5028 return "unknown-dereferenceable";
5029 bool IsKnownNonNull;
5030 bool IsAssumedNonNull = false;
5031 if (A)
5033 *A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5034 return std::string("dereferenceable") +
5035 (IsAssumedNonNull ? "" : "_or_null") +
5036 (isAssumedGlobal() ? "_globally" : "") + "<" +
5037 std::to_string(getKnownDereferenceableBytes()) + "-" +
5038 std::to_string(getAssumedDereferenceableBytes()) + ">" +
5039 (!A ? " [non-null is unknown]" : "");
5040 }
5041};
5042
5043/// Dereferenceable attribute for a floating value.
5044struct AADereferenceableFloating : AADereferenceableImpl {
5045 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
5046 : AADereferenceableImpl(IRP, A) {}
5047
5048 /// See AbstractAttribute::updateImpl(...).
5049 ChangeStatus updateImpl(Attributor &A) override {
5050 bool Stripped;
5051 bool UsedAssumedInformation = false;
5053 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5054 AA::AnyScope, UsedAssumedInformation)) {
5055 Values.push_back({getAssociatedValue(), getCtxI()});
5056 Stripped = false;
5057 } else {
5058 Stripped = Values.size() != 1 ||
5059 Values.front().getValue() != &getAssociatedValue();
5060 }
5061
5062 const DataLayout &DL = A.getDataLayout();
5063 DerefState T;
5064
5065 auto VisitValueCB = [&](const Value &V) -> bool {
5066 unsigned IdxWidth =
5067 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
5068 APInt Offset(IdxWidth, 0);
5070 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
5071 /* AllowNonInbounds */ true);
5072
5073 const auto *AA = A.getAAFor<AADereferenceable>(
5074 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
5075 int64_t DerefBytes = 0;
5076 if (!AA || (!Stripped && this == AA)) {
5077 // Use IR information if we did not strip anything.
5078 // TODO: track globally.
5079 bool CanBeNull, CanBeFreed;
5080 DerefBytes =
5081 Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
5082 T.GlobalState.indicatePessimisticFixpoint();
5083 } else {
5084 const DerefState &DS = AA->getState();
5085 DerefBytes = DS.DerefBytesState.getAssumed();
5086 T.GlobalState &= DS.GlobalState;
5087 }
5088
5089 // For now we do not try to "increase" dereferenceability due to negative
5090 // indices as we first have to come up with code to deal with loops and
5091 // for overflows of the dereferenceable bytes.
5092 int64_t OffsetSExt = Offset.getSExtValue();
5093 if (OffsetSExt < 0)
5094 OffsetSExt = 0;
5095
5096 T.takeAssumedDerefBytesMinimum(
5097 std::max(int64_t(0), DerefBytes - OffsetSExt));
5098
5099 if (this == AA) {
5100 if (!Stripped) {
5101 // If nothing was stripped IR information is all we got.
5102 T.takeKnownDerefBytesMaximum(
5103 std::max(int64_t(0), DerefBytes - OffsetSExt));
5104 T.indicatePessimisticFixpoint();
5105 } else if (OffsetSExt > 0) {
5106 // If something was stripped but there is circular reasoning we look
5107 // for the offset. If it is positive we basically decrease the
5108 // dereferenceable bytes in a circular loop now, which will simply
5109 // drive them down to the known value in a very slow way which we
5110 // can accelerate.
5111 T.indicatePessimisticFixpoint();
5112 }
5113 }
5114
5115 return T.isValidState();
5116 };
5117
5118 for (const auto &VAC : Values)
5119 if (!VisitValueCB(*VAC.getValue()))
5120 return indicatePessimisticFixpoint();
5121
5122 return clampStateAndIndicateChange(getState(), T);
5123 }
5124
5125 /// See AbstractAttribute::trackStatistics()
5126 void trackStatistics() const override {
5127 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
5128 }
5129};
5130
5131/// Dereferenceable attribute for a return value.
5132struct AADereferenceableReturned final
5133 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5134 using Base =
5135 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5136 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5137 : Base(IRP, A) {}
5138
5139 /// See AbstractAttribute::trackStatistics()
5140 void trackStatistics() const override {
5141 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
5142 }
5143};
5144
5145/// Dereferenceable attribute for an argument
5146struct AADereferenceableArgument final
5147 : AAArgumentFromCallSiteArguments<AADereferenceable,
5148 AADereferenceableImpl> {
5149 using Base =
5150 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5151 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5152 : Base(IRP, A) {}
5153
5154 /// See AbstractAttribute::trackStatistics()
5155 void trackStatistics() const override {
5156 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
5157 }
5158};
5159
5160/// Dereferenceable attribute for a call site argument.
5161struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5162 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5163 : AADereferenceableFloating(IRP, A) {}
5164
5165 /// See AbstractAttribute::trackStatistics()
5166 void trackStatistics() const override {
5167 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
5168 }
5169};
5170
5171/// Dereferenceable attribute deduction for a call site return value.
5172struct AADereferenceableCallSiteReturned final
5173 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5174 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5175 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5176 : Base(IRP, A) {}
5177
5178 /// See AbstractAttribute::trackStatistics()
5179 void trackStatistics() const override {
5180 STATS_DECLTRACK_CS_ATTR(dereferenceable);
5181 }
5182};
5183} // namespace
5184
5185// ------------------------ Align Argument Attribute ------------------------
5186
5187namespace {
5188
5189static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5190 Value &AssociatedValue, const Use *U,
5191 const Instruction *I, bool &TrackUse) {
5192 // We need to follow common pointer manipulation uses to the accesses they
5193 // feed into.
5194 if (isa<CastInst>(I)) {
5195 // Follow all but ptr2int casts.
5196 TrackUse = !isa<PtrToIntInst>(I);
5197 return 0;
5198 }
5199 if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
5200 if (GEP->hasAllConstantIndices())
5201 TrackUse = true;
5202 return 0;
5203 }
5204 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
5205 switch (II->getIntrinsicID()) {
5206 case Intrinsic::ptrmask: {
5207 // Is it appropriate to pull attribute in initialization?
5208 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5209 QueryingAA, IRPosition::value(*II->getOperand(1)), DepClassTy::NONE);
5210 const auto *AlignAA = A.getAAFor<AAAlign>(
5211 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5212 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5213 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5215 Align ConstAlign(UINT64_C(1) << ShiftValue);
5216 if (ConstAlign >= AlignAA->getKnownAlign())
5217 return Align(1).value();
5218 }
5219 if (AlignAA)
5220 return AlignAA->getKnownAlign().value();
5221 break;
5222 }
5223 case Intrinsic::amdgcn_make_buffer_rsrc: {
5224 const auto *AlignAA = A.getAAFor<AAAlign>(
5225 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5226 if (AlignAA)
5227 return AlignAA->getKnownAlign().value();
5228 break;
5229 }
5230 default:
5231 break;
5232 }
5233
5234 MaybeAlign MA;
5235 if (const auto *CB = dyn_cast<CallBase>(I)) {
5236 if (CB->isBundleOperand(U) || CB->isCallee(U))
5237 return 0;
5238
5239 unsigned ArgNo = CB->getArgOperandNo(U);
5240 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5241 // As long as we only use known information there is no need to track
5242 // dependences here.
5243 auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5244 if (AlignAA)
5245 MA = MaybeAlign(AlignAA->getKnownAlign());
5246 }
5247
5248 const DataLayout &DL = A.getDataLayout();
5249 const Value *UseV = U->get();
5250 if (auto *SI = dyn_cast<StoreInst>(I)) {
5251 if (SI->getPointerOperand() == UseV)
5252 MA = SI->getAlign();
5253 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5254 if (LI->getPointerOperand() == UseV)
5255 MA = LI->getAlign();
5256 } else if (auto *AI = dyn_cast<AtomicRMWInst>(I)) {
5257 if (AI->getPointerOperand() == UseV)
5258 MA = AI->getAlign();
5259 } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
5260 if (AI->getPointerOperand() == UseV)
5261 MA = AI->getAlign();
5262 }
5263
5264 if (!MA || *MA <= QueryingAA.getKnownAlign())
5265 return 0;
5266
5267 unsigned Alignment = MA->value();
5268 int64_t Offset;
5269
5270 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
5271 if (Base == &AssociatedValue) {
5272 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5273 // So we can say that the maximum power of two which is a divisor of
5274 // gcd(Offset, Alignment) is an alignment.
5275
5276 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5277 Alignment = llvm::bit_floor(gcd);
5278 }
5279 }
5280
5281 return Alignment;
5282}
5283
5284struct AAAlignImpl : AAAlign {
5285 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5286
5287 /// See AbstractAttribute::initialize(...).
5288 void initialize(Attributor &A) override {
5290 A.getAttrs(getIRPosition(), {Attribute::Alignment}, Attrs);
5291 for (const Attribute &Attr : Attrs)
5292 takeKnownMaximum(Attr.getValueAsInt());
5293
5294 Value &V = *getAssociatedValue().stripPointerCasts();
5295 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5296
5297 if (Instruction *CtxI = getCtxI())
5298 followUsesInMBEC(*this, A, getState(), *CtxI);
5299 }
5300
5301 /// See AbstractAttribute::manifest(...).
5302 ChangeStatus manifest(Attributor &A) override {
5303 ChangeStatus InstrChanged = ChangeStatus::UNCHANGED;
5304
5305 // Check for users that allow alignment annotations.
5306 Value &AssociatedValue = getAssociatedValue();
5307 if (isa<ConstantData>(AssociatedValue))
5308 return ChangeStatus::UNCHANGED;
5309
5310 for (const Use &U : AssociatedValue.uses()) {
5311 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5312 if (SI->getPointerOperand() == &AssociatedValue)
5313 if (SI->getAlign() < getAssumedAlign()) {
5314 STATS_DECLTRACK(AAAlign, Store,
5315 "Number of times alignment added to a store");
5316 SI->setAlignment(getAssumedAlign());
5317 InstrChanged = ChangeStatus::CHANGED;
5318 }
5319 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5320 if (LI->getPointerOperand() == &AssociatedValue)
5321 if (LI->getAlign() < getAssumedAlign()) {
5322 LI->setAlignment(getAssumedAlign());
5323 STATS_DECLTRACK(AAAlign, Load,
5324 "Number of times alignment added to a load");
5325 InstrChanged = ChangeStatus::CHANGED;
5326 }
5327 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(U.getUser())) {
5328 if (RMW->getPointerOperand() == &AssociatedValue) {
5329 if (RMW->getAlign() < getAssumedAlign()) {
5330 STATS_DECLTRACK(AAAlign, AtomicRMW,
5331 "Number of times alignment added to atomicrmw");
5332
5333 RMW->setAlignment(getAssumedAlign());
5334 InstrChanged = ChangeStatus::CHANGED;
5335 }
5336 }
5337 } else if (auto *CAS = dyn_cast<AtomicCmpXchgInst>(U.getUser())) {
5338 if (CAS->getPointerOperand() == &AssociatedValue) {
5339 if (CAS->getAlign() < getAssumedAlign()) {
5340 STATS_DECLTRACK(AAAlign, AtomicCmpXchg,
5341 "Number of times alignment added to cmpxchg");
5342 CAS->setAlignment(getAssumedAlign());
5343 InstrChanged = ChangeStatus::CHANGED;
5344 }
5345 }
5346 }
5347 }
5348
5349 ChangeStatus Changed = AAAlign::manifest(A);
5350
5351 Align InheritAlign =
5352 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5353 if (InheritAlign >= getAssumedAlign())
5354 return InstrChanged;
5355 return Changed | InstrChanged;
5356 }
5357
5358 // TODO: Provide a helper to determine the implied ABI alignment and check in
5359 // the existing manifest method and a new one for AAAlignImpl that value
5360 // to avoid making the alignment explicit if it did not improve.
5361
5362 /// See AbstractAttribute::getDeducedAttributes
5363 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5364 SmallVectorImpl<Attribute> &Attrs) const override {
5365 if (getAssumedAlign() > 1)
5366 Attrs.emplace_back(
5367 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5368 }
5369
5370 /// See followUsesInMBEC
5371 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5372 AAAlign::StateType &State) {
5373 bool TrackUse = false;
5374
5375 unsigned int KnownAlign =
5376 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5377 State.takeKnownMaximum(KnownAlign);
5378
5379 return TrackUse;
5380 }
5381
5382 /// See AbstractAttribute::getAsStr().
5383 const std::string getAsStr(Attributor *A) const override {
5384 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5385 std::to_string(getAssumedAlign().value()) + ">";
5386 }
5387};
5388
5389/// Align attribute for a floating value.
5390struct AAAlignFloating : AAAlignImpl {
5391 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5392
5393 /// See AbstractAttribute::updateImpl(...).
5394 ChangeStatus updateImpl(Attributor &A) override {
5395 const DataLayout &DL = A.getDataLayout();
5396
5397 bool Stripped;
5398 bool UsedAssumedInformation = false;
5400 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5401 AA::AnyScope, UsedAssumedInformation)) {
5402 Values.push_back({getAssociatedValue(), getCtxI()});
5403 Stripped = false;
5404 } else {
5405 Stripped = Values.size() != 1 ||
5406 Values.front().getValue() != &getAssociatedValue();
5407 }
5408
5409 StateType T;
5410 auto VisitValueCB = [&](Value &V) -> bool {
5412 return true;
5413 const auto *AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5414 DepClassTy::REQUIRED);
5415 if (!AA || (!Stripped && this == AA)) {
5416 int64_t Offset;
5417 unsigned Alignment = 1;
5418 if (const Value *Base =
5420 // TODO: Use AAAlign for the base too.
5421 Align PA = Base->getPointerAlignment(DL);
5422 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5423 // So we can say that the maximum power of two which is a divisor of
5424 // gcd(Offset, Alignment) is an alignment.
5425
5426 uint32_t gcd =
5427 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5428 Alignment = llvm::bit_floor(gcd);
5429 } else {
5430 Alignment = V.getPointerAlignment(DL).value();
5431 }
5432 // Use only IR information if we did not strip anything.
5433 T.takeKnownMaximum(Alignment);
5434 T.indicatePessimisticFixpoint();
5435 } else {
5436 // Use abstract attribute information.
5437 const AAAlign::StateType &DS = AA->getState();
5438 T ^= DS;
5439 }
5440 return T.isValidState();
5441 };
5442
5443 for (const auto &VAC : Values) {
5444 if (!VisitValueCB(*VAC.getValue()))
5445 return indicatePessimisticFixpoint();
5446 }
5447
5448 // TODO: If we know we visited all incoming values, thus no are assumed
5449 // dead, we can take the known information from the state T.
5450 return clampStateAndIndicateChange(getState(), T);
5451 }
5452
5453 /// See AbstractAttribute::trackStatistics()
5454 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
5455};
5456
5457/// Align attribute for function return value.
5458struct AAAlignReturned final
5459 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5460 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5461 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5462
5463 /// See AbstractAttribute::trackStatistics()
5464 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
5465};
5466
5467/// Align attribute for function argument.
5468struct AAAlignArgument final
5469 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5470 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5471 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5472
5473 /// See AbstractAttribute::manifest(...).
5474 ChangeStatus manifest(Attributor &A) override {
5475 // If the associated argument is involved in a must-tail call we give up
5476 // because we would need to keep the argument alignments of caller and
5477 // callee in-sync. Just does not seem worth the trouble right now.
5478 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5479 return ChangeStatus::UNCHANGED;
5480 return Base::manifest(A);
5481 }
5482
5483 /// See AbstractAttribute::trackStatistics()
5484 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
5485};
5486
5487struct AAAlignCallSiteArgument final : AAAlignFloating {
5488 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5489 : AAAlignFloating(IRP, A) {}
5490
5491 /// See AbstractAttribute::manifest(...).
5492 ChangeStatus manifest(Attributor &A) override {
5493 // If the associated argument is involved in a must-tail call we give up
5494 // because we would need to keep the argument alignments of caller and
5495 // callee in-sync. Just does not seem worth the trouble right now.
5496 if (Argument *Arg = getAssociatedArgument())
5497 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5498 return ChangeStatus::UNCHANGED;
5499 ChangeStatus Changed = AAAlignImpl::manifest(A);
5500 Align InheritAlign =
5501 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5502 if (InheritAlign >= getAssumedAlign())
5503 Changed = ChangeStatus::UNCHANGED;
5504 return Changed;
5505 }
5506
5507 /// See AbstractAttribute::updateImpl(Attributor &A).
5508 ChangeStatus updateImpl(Attributor &A) override {
5509 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5510 if (Argument *Arg = getAssociatedArgument()) {
5511 // We only take known information from the argument
5512 // so we do not need to track a dependence.
5513 const auto *ArgAlignAA = A.getAAFor<AAAlign>(
5514 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5515 if (ArgAlignAA)
5516 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5517 }
5518 return Changed;
5519 }
5520
5521 /// See AbstractAttribute::trackStatistics()
5522 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
5523};
5524
5525/// Align attribute deduction for a call site return value.
5526struct AAAlignCallSiteReturned final
5527 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5528 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5529 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5530 : Base(IRP, A) {}
5531
5532 ChangeStatus updateImpl(Attributor &A) override {
5533 Instruction *I = getIRPosition().getCtxI();
5534 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
5535 switch (II->getIntrinsicID()) {
5536 case Intrinsic::ptrmask: {
5537 Align Alignment;
5538 bool Valid = false;
5539
5540 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5541 *this, IRPosition::value(*II->getOperand(1)), DepClassTy::REQUIRED);
5542 if (ConstVals && ConstVals->isValidState()) {
5543 unsigned ShiftValue =
5544 std::min(ConstVals->getAssumedMinTrailingZeros(),
5545 Value::MaxAlignmentExponent);
5546 Alignment = Align(UINT64_C(1) << ShiftValue);
5547 Valid = true;
5548 }
5549
5550 const auto *AlignAA =
5551 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5552 DepClassTy::REQUIRED);
5553 if (AlignAA) {
5554 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5555 Valid = true;
5556 }
5557
5558 if (Valid)
5560 this->getState(),
5561 std::min(this->getAssumedAlign(), Alignment).value());
5562 break;
5563 }
5564 // FIXME: Should introduce target specific sub-attributes and letting
5565 // getAAfor<AAAlign> lead to create sub-attribute to handle target
5566 // specific intrinsics.
5567 case Intrinsic::amdgcn_make_buffer_rsrc: {
5568 const auto *AlignAA =
5569 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5570 DepClassTy::REQUIRED);
5571 if (AlignAA)
5573 this->getState(), AlignAA->getAssumedAlign().value());
5574 break;
5575 }
5576 default:
5577 break;
5578 }
5579 }
5580 return Base::updateImpl(A);
5581 };
5582 /// See AbstractAttribute::trackStatistics()
5583 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
5584};
5585} // namespace
5586
5587/// ------------------ Function No-Return Attribute ----------------------------
5588namespace {
5589struct AANoReturnImpl : public AANoReturn {
5590 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5591
5592 /// See AbstractAttribute::initialize(...).
5593 void initialize(Attributor &A) override {
5594 bool IsKnown;
5596 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5597 (void)IsKnown;
5598 }
5599
5600 /// See AbstractAttribute::getAsStr().
5601 const std::string getAsStr(Attributor *A) const override {
5602 return getAssumed() ? "noreturn" : "may-return";
5603 }
5604
5605 /// See AbstractAttribute::updateImpl(Attributor &A).
5606 ChangeStatus updateImpl(Attributor &A) override {
5607 auto CheckForNoReturn = [](Instruction &) { return false; };
5608 bool UsedAssumedInformation = false;
5609 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5610 {(unsigned)Instruction::Ret},
5611 UsedAssumedInformation))
5612 return indicatePessimisticFixpoint();
5613 return ChangeStatus::UNCHANGED;
5614 }
5615};
5616
5617struct AANoReturnFunction final : AANoReturnImpl {
5618 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5619 : AANoReturnImpl(IRP, A) {}
5620
5621 /// See AbstractAttribute::trackStatistics()
5622 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
5623};
5624
5625/// NoReturn attribute deduction for a call sites.
5626struct AANoReturnCallSite final
5627 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5628 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5629 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP, A) {}
5630
5631 /// See AbstractAttribute::trackStatistics()
5632 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
5633};
5634} // namespace
5635
5636/// ----------------------- Instance Info ---------------------------------
5637
5638namespace {
5639/// A class to hold the state of for no-capture attributes.
5640struct AAInstanceInfoImpl : public AAInstanceInfo {
5641 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5642 : AAInstanceInfo(IRP, A) {}
5643
5644 /// See AbstractAttribute::initialize(...).
5645 void initialize(Attributor &A) override {
5646 Value &V = getAssociatedValue();
5647 if (auto *C = dyn_cast<Constant>(&V)) {
5648 if (C->isThreadDependent())
5649 indicatePessimisticFixpoint();
5650 else
5651 indicateOptimisticFixpoint();
5652 return;
5653 }
5654 if (auto *CB = dyn_cast<CallBase>(&V))
5655 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5656 !CB->mayReadFromMemory()) {
5657 indicateOptimisticFixpoint();
5658 return;
5659 }
5660 if (auto *I = dyn_cast<Instruction>(&V)) {
5661 const auto *CI =
5662 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5663 *I->getFunction());
5664 if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
5665 indicatePessimisticFixpoint();
5666 return;
5667 }
5668 }
5669 }
5670
5671 /// See AbstractAttribute::updateImpl(...).
5672 ChangeStatus updateImpl(Attributor &A) override {
5673 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5674
5675 Value &V = getAssociatedValue();
5676 const Function *Scope = nullptr;
5677 if (auto *I = dyn_cast<Instruction>(&V))
5678 Scope = I->getFunction();
5679 if (auto *A = dyn_cast<Argument>(&V)) {
5680 Scope = A->getParent();
5681 if (!Scope->hasLocalLinkage())
5682 return Changed;
5683 }
5684 if (!Scope)
5685 return indicateOptimisticFixpoint();
5686
5687 bool IsKnownNoRecurse;
5689 A, this, IRPosition::function(*Scope), DepClassTy::OPTIONAL,
5690 IsKnownNoRecurse))
5691 return Changed;
5692
5693 auto UsePred = [&](const Use &U, bool &Follow) {
5694 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5695 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5696 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5697 Follow = true;
5698 return true;
5699 }
5700 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5701 (isa<StoreInst>(UserI) &&
5702 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5703 return true;
5704 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5705 // This check is not guaranteeing uniqueness but for now that we cannot
5706 // end up with two versions of \p U thinking it was one.
5708 if (!Callee || !Callee->hasLocalLinkage())
5709 return true;
5710 if (!CB->isArgOperand(&U))
5711 return false;
5712 const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5714 DepClassTy::OPTIONAL);
5715 if (!ArgInstanceInfoAA ||
5716 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5717 return false;
5718 // If this call base might reach the scope again we might forward the
5719 // argument back here. This is very conservative.
5721 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5722 [Scope](const Function &Fn) { return &Fn != Scope; }))
5723 return false;
5724 return true;
5725 }
5726 return false;
5727 };
5728
5729 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5730 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5731 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5732 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5733 AA::isDynamicallyUnique(A, *this, *Ptr))
5734 return true;
5735 }
5736 return false;
5737 };
5738
5739 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5740 DepClassTy::OPTIONAL,
5741 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5742 return indicatePessimisticFixpoint();
5743
5744 return Changed;
5745 }
5746
5747 /// See AbstractState::getAsStr().
5748 const std::string getAsStr(Attributor *A) const override {
5749 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5750 }
5751
5752 /// See AbstractAttribute::trackStatistics()
5753 void trackStatistics() const override {}
5754};
5755
5756/// InstanceInfo attribute for floating values.
5757struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5758 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5759 : AAInstanceInfoImpl(IRP, A) {}
5760};
5761
5762/// NoCapture attribute for function arguments.
5763struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5764 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5765 : AAInstanceInfoFloating(IRP, A) {}
5766};
5767
5768/// InstanceInfo attribute for call site arguments.
5769struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5770 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5771 : AAInstanceInfoImpl(IRP, A) {}
5772
5773 /// See AbstractAttribute::updateImpl(...).
5774 ChangeStatus updateImpl(Attributor &A) override {
5775 // TODO: Once we have call site specific value information we can provide
5776 // call site specific liveness information and then it makes
5777 // sense to specialize attributes for call sites arguments instead of
5778 // redirecting requests to the callee argument.
5779 Argument *Arg = getAssociatedArgument();
5780 if (!Arg)
5781 return indicatePessimisticFixpoint();
5782 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5783 auto *ArgAA =
5784 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5785 if (!ArgAA)
5786 return indicatePessimisticFixpoint();
5787 return clampStateAndIndicateChange(getState(), ArgAA->getState());
5788 }
5789};
5790
5791/// InstanceInfo attribute for function return value.
5792struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5793 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5794 : AAInstanceInfoImpl(IRP, A) {
5795 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5796 }
5797
5798 /// See AbstractAttribute::initialize(...).
5799 void initialize(Attributor &A) override {
5800 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5801 }
5802
5803 /// See AbstractAttribute::updateImpl(...).
5804 ChangeStatus updateImpl(Attributor &A) override {
5805 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5806 }
5807};
5808
5809/// InstanceInfo attribute deduction for a call site return value.
5810struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5811 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5812 : AAInstanceInfoFloating(IRP, A) {}
5813};
5814} // namespace
5815
5816/// ----------------------- Variable Capturing ---------------------------------
5818 Attribute::AttrKind ImpliedAttributeKind,
5819 bool IgnoreSubsumingPositions) {
5820 assert(ImpliedAttributeKind == Attribute::Captures &&
5821 "Unexpected attribute kind");
5822 Value &V = IRP.getAssociatedValue();
5823 if (!isa<Constant>(V) && !IRP.isArgumentPosition())
5824 return V.use_empty();
5825
5826 // You cannot "capture" null in the default address space.
5827 //
5828 // FIXME: This should use NullPointerIsDefined to account for the function
5829 // attribute.
5831 V.getType()->getPointerAddressSpace() == 0)) {
5832 return true;
5833 }
5834
5836 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5837 /* IgnoreSubsumingPositions */ true);
5838 for (const Attribute &Attr : Attrs)
5839 if (capturesNothing(Attr.getCaptureInfo()))
5840 return true;
5841
5843 if (Argument *Arg = IRP.getAssociatedArgument()) {
5845 A.getAttrs(IRPosition::argument(*Arg),
5846 {Attribute::Captures, Attribute::ByVal}, Attrs,
5847 /* IgnoreSubsumingPositions */ true);
5848 bool ArgNoCapture = any_of(Attrs, [](Attribute Attr) {
5849 return Attr.getKindAsEnum() == Attribute::ByVal ||
5851 });
5852 if (ArgNoCapture) {
5853 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(
5854 V.getContext(), CaptureInfo::none()));
5855 return true;
5856 }
5857 }
5858
5859 if (const Function *F = IRP.getAssociatedFunction()) {
5860 // Check what state the associated function can actually capture.
5863 if (State.isKnown(NO_CAPTURE)) {
5864 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(V.getContext(),
5866 return true;
5867 }
5868 }
5869
5870 return false;
5871}
5872
5873/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5874/// depending on the ability of the function associated with \p IRP to capture
5875/// state in memory and through "returning/throwing", respectively.
5877 const Function &F,
5878 BitIntegerState &State) {
5879 // TODO: Once we have memory behavior attributes we should use them here.
5880
5881 // If we know we cannot communicate or write to memory, we do not care about
5882 // ptr2int anymore.
5883 bool ReadOnly = F.onlyReadsMemory();
5884 bool NoThrow = F.doesNotThrow();
5885 bool IsVoidReturn = F.getReturnType()->isVoidTy();
5886 if (ReadOnly && NoThrow && IsVoidReturn) {
5887 State.addKnownBits(NO_CAPTURE);
5888 return;
5889 }
5890
5891 // A function cannot capture state in memory if it only reads memory, it can
5892 // however return/throw state and the state might be influenced by the
5893 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5894 if (ReadOnly)
5895 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5896
5897 // A function cannot communicate state back if it does not through
5898 // exceptions and doesn not return values.
5899 if (NoThrow && IsVoidReturn)
5900 State.addKnownBits(NOT_CAPTURED_IN_RET);
5901
5902 // Check existing "returned" attributes.
5903 int ArgNo = IRP.getCalleeArgNo();
5904 if (!NoThrow || ArgNo < 0 ||
5905 !F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5906 return;
5907
5908 for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
5909 if (F.hasParamAttribute(U, Attribute::Returned)) {
5910 if (U == unsigned(ArgNo))
5911 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5912 else if (ReadOnly)
5913 State.addKnownBits(NO_CAPTURE);
5914 else
5915 State.addKnownBits(NOT_CAPTURED_IN_RET);
5916 break;
5917 }
5918}
5919
5920namespace {
5921/// A class to hold the state of for no-capture attributes.
5922struct AANoCaptureImpl : public AANoCapture {
5923 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5924
5925 /// See AbstractAttribute::initialize(...).
5926 void initialize(Attributor &A) override {
5927 bool IsKnown;
5929 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5930 (void)IsKnown;
5931 }
5932
5933 /// See AbstractAttribute::updateImpl(...).
5934 ChangeStatus updateImpl(Attributor &A) override;
5935
5936 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
5937 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5938 SmallVectorImpl<Attribute> &Attrs) const override {
5939 if (!isAssumedNoCaptureMaybeReturned())
5940 return;
5941
5942 if (isArgumentPosition()) {
5943 if (isAssumedNoCapture())
5944 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
5945 else if (ManifestInternal)
5946 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
5947 }
5948 }
5949
5950 /// See AbstractState::getAsStr().
5951 const std::string getAsStr(Attributor *A) const override {
5952 if (isKnownNoCapture())
5953 return "known not-captured";
5954 if (isAssumedNoCapture())
5955 return "assumed not-captured";
5956 if (isKnownNoCaptureMaybeReturned())
5957 return "known not-captured-maybe-returned";
5958 if (isAssumedNoCaptureMaybeReturned())
5959 return "assumed not-captured-maybe-returned";
5960 return "assumed-captured";
5961 }
5962
5963 /// Check the use \p U and update \p State accordingly. Return true if we
5964 /// should continue to update the state.
5965 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
5966 bool &Follow) {
5967 Instruction *UInst = cast<Instruction>(U.getUser());
5968 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
5969 << *UInst << "\n");
5970
5971 // Deal with ptr2int by following uses.
5972 if (isa<PtrToIntInst>(UInst)) {
5973 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
5974 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5975 /* Return */ true);
5976 }
5977
5978 // For stores we already checked if we can follow them, if they make it
5979 // here we give up.
5980 if (isa<StoreInst>(UInst))
5981 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5982 /* Return */ true);
5983
5984 // Explicitly catch return instructions.
5985 if (isa<ReturnInst>(UInst)) {
5986 if (UInst->getFunction() == getAnchorScope())
5987 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
5988 /* Return */ true);
5989 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5990 /* Return */ true);
5991 }
5992
5993 // For now we only use special logic for call sites. However, the tracker
5994 // itself knows about a lot of other non-capturing cases already.
5995 auto *CB = dyn_cast<CallBase>(UInst);
5996 if (!CB || !CB->isArgOperand(&U))
5997 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
5998 /* Return */ true);
5999
6000 unsigned ArgNo = CB->getArgOperandNo(&U);
6001 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
6002 // If we have a abstract no-capture attribute for the argument we can use
6003 // it to justify a non-capture attribute here. This allows recursion!
6004 bool IsKnownNoCapture;
6005 const AANoCapture *ArgNoCaptureAA = nullptr;
6006 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
6007 A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6008 &ArgNoCaptureAA);
6009 if (IsAssumedNoCapture)
6010 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
6011 /* Return */ false);
6012 if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
6013 Follow = true;
6014 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
6015 /* Return */ false);
6016 }
6017
6018 // Lastly, we could not find a reason no-capture can be assumed so we don't.
6019 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6020 /* Return */ true);
6021 }
6022
6023 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
6024 /// \p CapturedInRet, then return true if we should continue updating the
6025 /// state.
6026 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
6027 bool CapturedInInt, bool CapturedInRet) {
6028 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
6029 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
6030 if (CapturedInMem)
6031 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
6032 if (CapturedInInt)
6033 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
6034 if (CapturedInRet)
6035 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
6036 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
6037 }
6038};
6039
6040ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
6041 const IRPosition &IRP = getIRPosition();
6042 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
6043 : &IRP.getAssociatedValue();
6044 if (!V)
6045 return indicatePessimisticFixpoint();
6046
6047 const Function *F =
6048 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
6049
6050 // TODO: Is the checkForAllUses below useful for constants?
6051 if (!F)
6052 return indicatePessimisticFixpoint();
6053
6055 const IRPosition &FnPos = IRPosition::function(*F);
6056
6057 // Readonly means we cannot capture through memory.
6058 bool IsKnown;
6059 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
6060 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6061 if (IsKnown)
6062 addKnownBits(NOT_CAPTURED_IN_MEM);
6063 }
6064
6065 // Make sure all returned values are different than the underlying value.
6066 // TODO: we could do this in a more sophisticated way inside
6067 // AAReturnedValues, e.g., track all values that escape through returns
6068 // directly somehow.
6069 auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
6071 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,
6073 UsedAssumedInformation))
6074 return false;
6075 bool SeenConstant = false;
6076 for (const AA::ValueAndContext &VAC : Values) {
6077 if (isa<Constant>(VAC.getValue())) {
6078 if (SeenConstant)
6079 return false;
6080 SeenConstant = true;
6081 } else if (!isa<Argument>(VAC.getValue()) ||
6082 VAC.getValue() == getAssociatedArgument())
6083 return false;
6084 }
6085 return true;
6086 };
6087
6088 bool IsKnownNoUnwind;
6090 A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
6091 bool IsVoidTy = F->getReturnType()->isVoidTy();
6092 bool UsedAssumedInformation = false;
6093 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6094 T.addKnownBits(NOT_CAPTURED_IN_RET);
6095 if (T.isKnown(NOT_CAPTURED_IN_MEM))
6097 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6098 addKnownBits(NOT_CAPTURED_IN_RET);
6099 if (isKnown(NOT_CAPTURED_IN_MEM))
6100 return indicateOptimisticFixpoint();
6101 }
6102 }
6103 }
6104
6105 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6106 // TODO(captures): Make this more precise.
6107 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
6108 if (capturesNothing(CI))
6109 return true;
6110 if (CI.isPassthrough()) {
6111 Follow = true;
6112 return true;
6113 }
6114 return checkUse(A, T, U, Follow);
6115 };
6116
6117 if (!A.checkForAllUses(UseCheck, *this, *V))
6118 return indicatePessimisticFixpoint();
6119
6120 AANoCapture::StateType &S = getState();
6121 auto Assumed = S.getAssumed();
6122 S.intersectAssumedBits(T.getAssumed());
6123 if (!isAssumedNoCaptureMaybeReturned())
6124 return indicatePessimisticFixpoint();
6125 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6127}
6128
6129/// NoCapture attribute for function arguments.
6130struct AANoCaptureArgument final : AANoCaptureImpl {
6131 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6132 : AANoCaptureImpl(IRP, A) {}
6133
6134 /// See AbstractAttribute::trackStatistics()
6135 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
6136};
6137
6138/// NoCapture attribute for call site arguments.
6139struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6140 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6141 : AANoCaptureImpl(IRP, A) {}
6142
6143 /// See AbstractAttribute::updateImpl(...).
6144 ChangeStatus updateImpl(Attributor &A) override {
6145 // TODO: Once we have call site specific value information we can provide
6146 // call site specific liveness information and then it makes
6147 // sense to specialize attributes for call sites arguments instead of
6148 // redirecting requests to the callee argument.
6149 Argument *Arg = getAssociatedArgument();
6150 if (!Arg)
6151 return indicatePessimisticFixpoint();
6152 const IRPosition &ArgPos = IRPosition::argument(*Arg);
6153 bool IsKnownNoCapture;
6154 const AANoCapture *ArgAA = nullptr;
6156 A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6157 &ArgAA))
6158 return ChangeStatus::UNCHANGED;
6159 if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
6160 return indicatePessimisticFixpoint();
6161 return clampStateAndIndicateChange(getState(), ArgAA->getState());
6162 }
6163
6164 /// See AbstractAttribute::trackStatistics()
6165 void trackStatistics() const override {
6167 };
6168};
6169
6170/// NoCapture attribute for floating values.
6171struct AANoCaptureFloating final : AANoCaptureImpl {
6172 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6173 : AANoCaptureImpl(IRP, A) {}
6174
6175 /// See AbstractAttribute::trackStatistics()
6176 void trackStatistics() const override {
6178 }
6179};
6180
6181/// NoCapture attribute for function return value.
6182struct AANoCaptureReturned final : AANoCaptureImpl {
6183 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6184 : AANoCaptureImpl(IRP, A) {
6185 llvm_unreachable("NoCapture is not applicable to function returns!");
6186 }
6187
6188 /// See AbstractAttribute::initialize(...).
6189 void initialize(Attributor &A) override {
6190 llvm_unreachable("NoCapture is not applicable to function returns!");
6191 }
6192
6193 /// See AbstractAttribute::updateImpl(...).
6194 ChangeStatus updateImpl(Attributor &A) override {
6195 llvm_unreachable("NoCapture is not applicable to function returns!");
6196 }
6197
6198 /// See AbstractAttribute::trackStatistics()
6199 void trackStatistics() const override {}
6200};
6201
6202/// NoCapture attribute deduction for a call site return value.
6203struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6204 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6205 : AANoCaptureImpl(IRP, A) {}
6206
6207 /// See AbstractAttribute::initialize(...).
6208 void initialize(Attributor &A) override {
6209 const Function *F = getAnchorScope();
6210 // Check what state the associated function can actually capture.
6211 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6212 }
6213
6214 /// See AbstractAttribute::trackStatistics()
6215 void trackStatistics() const override {
6217 }
6218};
6219} // namespace
6220
6221/// ------------------ Value Simplify Attribute ----------------------------
6222
6223bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6224 // FIXME: Add a typecast support.
6227 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6228 return false;
6229
6230 LLVM_DEBUG({
6232 dbgs() << "[ValueSimplify] is assumed to be "
6233 << **SimplifiedAssociatedValue << "\n";
6234 else
6235 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6236 });
6237 return true;
6238}
6239
6240namespace {
6241struct AAValueSimplifyImpl : AAValueSimplify {
6242 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6243 : AAValueSimplify(IRP, A) {}
6244
6245 /// See AbstractAttribute::initialize(...).
6246 void initialize(Attributor &A) override {
6247 if (getAssociatedValue().getType()->isVoidTy())
6248 indicatePessimisticFixpoint();
6249 if (A.hasSimplificationCallback(getIRPosition()))
6250 indicatePessimisticFixpoint();
6251 }
6252
6253 /// See AbstractAttribute::getAsStr().
6254 const std::string getAsStr(Attributor *A) const override {
6255 LLVM_DEBUG({
6256 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6257 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6258 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6259 });
6260 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6261 : "not-simple";
6262 }
6263
6264 /// See AbstractAttribute::trackStatistics()
6265 void trackStatistics() const override {}
6266
6267 /// See AAValueSimplify::getAssumedSimplifiedValue()
6268 std::optional<Value *>
6269 getAssumedSimplifiedValue(Attributor &A) const override {
6270 return SimplifiedAssociatedValue;
6271 }
6272
6273 /// Ensure the return value is \p V with type \p Ty, if not possible return
6274 /// nullptr. If \p Check is true we will only verify such an operation would
6275 /// suceed and return a non-nullptr value if that is the case. No IR is
6276 /// generated or modified.
6277 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6278 bool Check) {
6279 if (auto *TypedV = AA::getWithType(V, Ty))
6280 return TypedV;
6281 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6282 return Check ? &V
6283 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6284 &V, &Ty, "", CtxI->getIterator());
6285 return nullptr;
6286 }
6287
6288 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6289 /// If \p Check is true we will only verify such an operation would suceed and
6290 /// return a non-nullptr value if that is the case. No IR is generated or
6291 /// modified.
6292 static Value *reproduceInst(Attributor &A,
6293 const AbstractAttribute &QueryingAA,
6294 Instruction &I, Type &Ty, Instruction *CtxI,
6295 bool Check, ValueToValueMapTy &VMap) {
6296 assert(CtxI && "Cannot reproduce an instruction without context!");
6297 if (Check && (I.mayReadFromMemory() ||
6298 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6299 /* TLI */ nullptr)))
6300 return nullptr;
6301 for (Value *Op : I.operands()) {
6302 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6303 if (!NewOp) {
6304 assert(Check && "Manifest of new value unexpectedly failed!");
6305 return nullptr;
6306 }
6307 if (!Check)
6308 VMap[Op] = NewOp;
6309 }
6310 if (Check)
6311 return &I;
6312
6313 Instruction *CloneI = I.clone();
6314 // TODO: Try to salvage debug information here.
6315 CloneI->setDebugLoc(DebugLoc());
6316 VMap[&I] = CloneI;
6317 CloneI->insertBefore(CtxI->getIterator());
6318 RemapInstruction(CloneI, VMap);
6319 return CloneI;
6320 }
6321
6322 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6323 /// If \p Check is true we will only verify such an operation would suceed and
6324 /// return a non-nullptr value if that is the case. No IR is generated or
6325 /// modified.
6326 static Value *reproduceValue(Attributor &A,
6327 const AbstractAttribute &QueryingAA, Value &V,
6328 Type &Ty, Instruction *CtxI, bool Check,
6329 ValueToValueMapTy &VMap) {
6330 if (const auto &NewV = VMap.lookup(&V))
6331 return NewV;
6332 bool UsedAssumedInformation = false;
6333 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6334 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6335 if (!SimpleV.has_value())
6336 return PoisonValue::get(&Ty);
6337 Value *EffectiveV = &V;
6338 if (*SimpleV)
6339 EffectiveV = *SimpleV;
6340 if (auto *C = dyn_cast<Constant>(EffectiveV))
6341 return C;
6342 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6343 A.getInfoCache()))
6344 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6345 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6346 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6347 return ensureType(A, *NewV, Ty, CtxI, Check);
6348 return nullptr;
6349 }
6350
6351 /// Return a value we can use as replacement for the associated one, or
6352 /// nullptr if we don't have one that makes sense.
6353 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6354 Value *NewV = SimplifiedAssociatedValue
6355 ? *SimplifiedAssociatedValue
6356 : UndefValue::get(getAssociatedType());
6357 if (NewV && NewV != &getAssociatedValue()) {
6358 ValueToValueMapTy VMap;
6359 // First verify we can reprduce the value with the required type at the
6360 // context location before we actually start modifying the IR.
6361 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6362 /* CheckOnly */ true, VMap))
6363 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6364 /* CheckOnly */ false, VMap);
6365 }
6366 return nullptr;
6367 }
6368
6369 /// Helper function for querying AAValueSimplify and updating candidate.
6370 /// \param IRP The value position we are trying to unify with SimplifiedValue
6371 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6372 const IRPosition &IRP, bool Simplify = true) {
6373 bool UsedAssumedInformation = false;
6374 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6375 if (Simplify)
6376 QueryingValueSimplified = A.getAssumedSimplified(
6377 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6378 return unionAssumed(QueryingValueSimplified);
6379 }
6380
6381 /// Returns a candidate is found or not
6382 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6383 if (!getAssociatedValue().getType()->isIntegerTy())
6384 return false;
6385
6386 // This will also pass the call base context.
6387 const auto *AA =
6388 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6389 if (!AA)
6390 return false;
6391
6392 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
6393
6394 if (!COpt) {
6395 SimplifiedAssociatedValue = std::nullopt;
6396 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6397 return true;
6398 }
6399 if (auto *C = *COpt) {
6400 SimplifiedAssociatedValue = C;
6401 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6402 return true;
6403 }
6404 return false;
6405 }
6406
6407 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6408 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6409 return true;
6410 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6411 return true;
6412 return false;
6413 }
6414
6415 /// See AbstractAttribute::manifest(...).
6416 ChangeStatus manifest(Attributor &A) override {
6417 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6418 for (auto &U : getAssociatedValue().uses()) {
6419 // Check if we need to adjust the insertion point to make sure the IR is
6420 // valid.
6421 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6422 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6423 IP = PHI->getIncomingBlock(U)->getTerminator();
6424 if (auto *NewV = manifestReplacementValue(A, IP)) {
6425 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6426 << " -> " << *NewV << " :: " << *this << "\n");
6427 if (A.changeUseAfterManifest(U, *NewV))
6428 Changed = ChangeStatus::CHANGED;
6429 }
6430 }
6431
6432 return Changed | AAValueSimplify::manifest(A);
6433 }
6434
6435 /// See AbstractState::indicatePessimisticFixpoint(...).
6436 ChangeStatus indicatePessimisticFixpoint() override {
6437 SimplifiedAssociatedValue = &getAssociatedValue();
6438 return AAValueSimplify::indicatePessimisticFixpoint();
6439 }
6440};
6441
6442struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6443 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6444 : AAValueSimplifyImpl(IRP, A) {}
6445
6446 void initialize(Attributor &A) override {
6447 AAValueSimplifyImpl::initialize(A);
6448 if (A.hasAttr(getIRPosition(),
6449 {Attribute::InAlloca, Attribute::Preallocated,
6450 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6451 /* IgnoreSubsumingPositions */ true))
6452 indicatePessimisticFixpoint();
6453 }
6454
6455 /// See AbstractAttribute::updateImpl(...).
6456 ChangeStatus updateImpl(Attributor &A) override {
6457 // Byval is only replacable if it is readonly otherwise we would write into
6458 // the replaced value and not the copy that byval creates implicitly.
6459 Argument *Arg = getAssociatedArgument();
6460 if (Arg->hasByValAttr()) {
6461 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6462 // there is no race by not copying a constant byval.
6463 bool IsKnown;
6464 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6465 return indicatePessimisticFixpoint();
6466 }
6467
6468 auto Before = SimplifiedAssociatedValue;
6469
6470 auto PredForCallSite = [&](AbstractCallSite ACS) {
6471 const IRPosition &ACSArgPos =
6472 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6473 // Check if a coresponding argument was found or if it is on not
6474 // associated (which can happen for callback calls).
6475 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6476 return false;
6477
6478 // Simplify the argument operand explicitly and check if the result is
6479 // valid in the current scope. This avoids refering to simplified values
6480 // in other functions, e.g., we don't want to say a an argument in a
6481 // static function is actually an argument in a different function.
6482 bool UsedAssumedInformation = false;
6483 std::optional<Constant *> SimpleArgOp =
6484 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6485 if (!SimpleArgOp)
6486 return true;
6487 if (!*SimpleArgOp)
6488 return false;
6489 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6490 return false;
6491 return unionAssumed(*SimpleArgOp);
6492 };
6493
6494 // Generate a answer specific to a call site context.
6495 bool Success;
6496 bool UsedAssumedInformation = false;
6497 if (hasCallBaseContext() &&
6498 getCallBaseContext()->getCalledOperand() == Arg->getParent())
6499 Success = PredForCallSite(
6500 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6501 else
6502 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6503 UsedAssumedInformation);
6504
6505 if (!Success)
6506 if (!askSimplifiedValueForOtherAAs(A))
6507 return indicatePessimisticFixpoint();
6508
6509 // If a candidate was found in this update, return CHANGED.
6510 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6511 : ChangeStatus ::CHANGED;
6512 }
6513
6514 /// See AbstractAttribute::trackStatistics()
6515 void trackStatistics() const override {
6516 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6517 }
6518};
6519
6520struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6521 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6522 : AAValueSimplifyImpl(IRP, A) {}
6523
6524 /// See AAValueSimplify::getAssumedSimplifiedValue()
6525 std::optional<Value *>
6526 getAssumedSimplifiedValue(Attributor &A) const override {
6527 if (!isValidState())
6528 return nullptr;
6529 return SimplifiedAssociatedValue;
6530 }
6531
6532 /// See AbstractAttribute::updateImpl(...).
6533 ChangeStatus updateImpl(Attributor &A) override {
6534 auto Before = SimplifiedAssociatedValue;
6535
6536 auto ReturnInstCB = [&](Instruction &I) {
6537 auto &RI = cast<ReturnInst>(I);
6538 return checkAndUpdate(
6539 A, *this,
6540 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6541 };
6542
6543 bool UsedAssumedInformation = false;
6544 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6545 UsedAssumedInformation))
6546 if (!askSimplifiedValueForOtherAAs(A))
6547 return indicatePessimisticFixpoint();
6548
6549 // If a candidate was found in this update, return CHANGED.
6550 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6551 : ChangeStatus ::CHANGED;
6552 }
6553
6554 ChangeStatus manifest(Attributor &A) override {
6555 // We queried AAValueSimplify for the returned values so they will be
6556 // replaced if a simplified form was found. Nothing to do here.
6557 return ChangeStatus::UNCHANGED;
6558 }
6559
6560 /// See AbstractAttribute::trackStatistics()
6561 void trackStatistics() const override {
6562 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6563 }
6564};
6565
6566struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6567 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6568 : AAValueSimplifyImpl(IRP, A) {}
6569
6570 /// See AbstractAttribute::initialize(...).
6571 void initialize(Attributor &A) override {
6572 AAValueSimplifyImpl::initialize(A);
6573 Value &V = getAnchorValue();
6574
6575 // TODO: add other stuffs
6576 if (isa<Constant>(V))
6577 indicatePessimisticFixpoint();
6578 }
6579
6580 /// See AbstractAttribute::updateImpl(...).
6581 ChangeStatus updateImpl(Attributor &A) override {
6582 auto Before = SimplifiedAssociatedValue;
6583 if (!askSimplifiedValueForOtherAAs(A))
6584 return indicatePessimisticFixpoint();
6585
6586 // If a candidate was found in this update, return CHANGED.
6587 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6588 : ChangeStatus ::CHANGED;
6589 }
6590
6591 /// See AbstractAttribute::trackStatistics()
6592 void trackStatistics() const override {
6593 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6594 }
6595};
6596
6597struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6598 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6599 : AAValueSimplifyImpl(IRP, A) {}
6600
6601 /// See AbstractAttribute::initialize(...).
6602 void initialize(Attributor &A) override {
6603 SimplifiedAssociatedValue = nullptr;
6604 indicateOptimisticFixpoint();
6605 }
6606 /// See AbstractAttribute::initialize(...).
6607 ChangeStatus updateImpl(Attributor &A) override {
6609 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6610 }
6611 /// See AbstractAttribute::trackStatistics()
6612 void trackStatistics() const override {
6613 STATS_DECLTRACK_FN_ATTR(value_simplify)
6614 }
6615};
6616
6617struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6618 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6619 : AAValueSimplifyFunction(IRP, A) {}
6620 /// See AbstractAttribute::trackStatistics()
6621 void trackStatistics() const override {
6622 STATS_DECLTRACK_CS_ATTR(value_simplify)
6623 }
6624};
6625
6626struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6627 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6628 : AAValueSimplifyImpl(IRP, A) {}
6629
6630 void initialize(Attributor &A) override {
6631 AAValueSimplifyImpl::initialize(A);
6632 Function *Fn = getAssociatedFunction();
6633 assert(Fn && "Did expect an associted function");
6634 for (Argument &Arg : Fn->args()) {
6635 if (Arg.hasReturnedAttr()) {
6636 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6637 Arg.getArgNo());
6639 checkAndUpdate(A, *this, IRP))
6640 indicateOptimisticFixpoint();
6641 else
6642 indicatePessimisticFixpoint();
6643 return;
6644 }
6645 }
6646 }
6647
6648 /// See AbstractAttribute::updateImpl(...).
6649 ChangeStatus updateImpl(Attributor &A) override {
6650 return indicatePessimisticFixpoint();
6651 }
6652
6653 void trackStatistics() const override {
6654 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6655 }
6656};
6657
6658struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6659 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6660 : AAValueSimplifyFloating(IRP, A) {}
6661
6662 /// See AbstractAttribute::manifest(...).
6663 ChangeStatus manifest(Attributor &A) override {
6664 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6665 // TODO: We should avoid simplification duplication to begin with.
6666 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6667 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6668 if (FloatAA && FloatAA->getState().isValidState())
6669 return Changed;
6670
6671 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6672 Use &U = cast<CallBase>(&getAnchorValue())
6673 ->getArgOperandUse(getCallSiteArgNo());
6674 if (A.changeUseAfterManifest(U, *NewV))
6675 Changed = ChangeStatus::CHANGED;
6676 }
6677
6678 return Changed | AAValueSimplify::manifest(A);
6679 }
6680
6681 void trackStatistics() const override {
6682 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6683 }
6684};
6685} // namespace
6686
6687/// ----------------------- Heap-To-Stack Conversion ---------------------------
6688namespace {
6689struct AAHeapToStackFunction final : public AAHeapToStack {
6690
6691 struct AllocationInfo {
6692 /// The call that allocates the memory.
6693 CallBase *const CB;
6694
6695 /// The library function id for the allocation.
6696 LibFunc LibraryFunctionId = NotLibFunc;
6697
6698 /// The status wrt. a rewrite.
6699 enum {
6700 STACK_DUE_TO_USE,
6701 STACK_DUE_TO_FREE,
6702 INVALID,
6703 } Status = STACK_DUE_TO_USE;
6704
6705 /// Flag to indicate if we encountered a use that might free this allocation
6706 /// but which is not in the deallocation infos.
6707 bool HasPotentiallyFreeingUnknownUses = false;
6708
6709 /// Flag to indicate that we should place the new alloca in the function
6710 /// entry block rather than where the call site (CB) is.
6711 bool MoveAllocaIntoEntry = true;
6712
6713 /// The set of free calls that use this allocation.
6714 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6715 };
6716
6717 struct DeallocationInfo {
6718 /// The call that deallocates the memory.
6719 CallBase *const CB;
6720 /// The value freed by the call.
6721 Value *FreedOp;
6722
6723 /// Flag to indicate if we don't know all objects this deallocation might
6724 /// free.
6725 bool MightFreeUnknownObjects = false;
6726
6727 /// The set of allocation calls that are potentially freed.
6728 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6729 };
6730
6731 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6732 : AAHeapToStack(IRP, A) {}
6733
6734 ~AAHeapToStackFunction() override {
6735 // Ensure we call the destructor so we release any memory allocated in the
6736 // sets.
6737 for (auto &It : AllocationInfos)
6738 It.second->~AllocationInfo();
6739 for (auto &It : DeallocationInfos)
6740 It.second->~DeallocationInfo();
6741 }
6742
6743 void initialize(Attributor &A) override {
6744 AAHeapToStack::initialize(A);
6745
6746 const Function *F = getAnchorScope();
6747 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6748
6749 auto AllocationIdentifierCB = [&](Instruction &I) {
6750 CallBase *CB = dyn_cast<CallBase>(&I);
6751 if (!CB)
6752 return true;
6753 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6754 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6755 return true;
6756 }
6757 // To do heap to stack, we need to know that the allocation itself is
6758 // removable once uses are rewritten, and that we can initialize the
6759 // alloca to the same pattern as the original allocation result.
6760 if (isRemovableAlloc(CB, TLI)) {
6761 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6762 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6763 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6764 AllocationInfos[CB] = AI;
6765 if (TLI)
6766 TLI->getLibFunc(*CB, AI->LibraryFunctionId);
6767 }
6768 }
6769 return true;
6770 };
6771
6772 bool UsedAssumedInformation = false;
6773 bool Success = A.checkForAllCallLikeInstructions(
6774 AllocationIdentifierCB, *this, UsedAssumedInformation,
6775 /* CheckBBLivenessOnly */ false,
6776 /* CheckPotentiallyDead */ true);
6777 (void)Success;
6778 assert(Success && "Did not expect the call base visit callback to fail!");
6779
6781 [](const IRPosition &, const AbstractAttribute *,
6782 bool &) -> std::optional<Value *> { return nullptr; };
6783 for (const auto &It : AllocationInfos)
6784 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6785 SCB);
6786 for (const auto &It : DeallocationInfos)
6787 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6788 SCB);
6789 }
6790
6791 const std::string getAsStr(Attributor *A) const override {
6792 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6793 for (const auto &It : AllocationInfos) {
6794 if (It.second->Status == AllocationInfo::INVALID)
6795 ++NumInvalidMallocs;
6796 else
6797 ++NumH2SMallocs;
6798 }
6799 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6800 std::to_string(NumInvalidMallocs);
6801 }
6802
6803 /// See AbstractAttribute::trackStatistics().
6804 void trackStatistics() const override {
6805 STATS_DECL(
6806 MallocCalls, Function,
6807 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6808 for (const auto &It : AllocationInfos)
6809 if (It.second->Status != AllocationInfo::INVALID)
6810 ++BUILD_STAT_NAME(MallocCalls, Function);
6811 }
6812
6813 bool isAssumedHeapToStack(const CallBase &CB) const override {
6814 if (isValidState())
6815 if (AllocationInfo *AI =
6816 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6817 return AI->Status != AllocationInfo::INVALID;
6818 return false;
6819 }
6820
6821 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6822 if (!isValidState())
6823 return false;
6824
6825 for (const auto &It : AllocationInfos) {
6826 AllocationInfo &AI = *It.second;
6827 if (AI.Status == AllocationInfo::INVALID)
6828 continue;
6829
6830 if (AI.PotentialFreeCalls.count(&CB))
6831 return true;
6832 }
6833
6834 return false;
6835 }
6836
6837 ChangeStatus manifest(Attributor &A) override {
6838 assert(getState().isValidState() &&
6839 "Attempted to manifest an invalid state!");
6840
6841 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6842 Function *F = getAnchorScope();
6843 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6844
6845 for (auto &It : AllocationInfos) {
6846 AllocationInfo &AI = *It.second;
6847 if (AI.Status == AllocationInfo::INVALID)
6848 continue;
6849
6850 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6851 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6852 A.deleteAfterManifest(*FreeCall);
6853 HasChanged = ChangeStatus::CHANGED;
6854 }
6855
6856 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6857 << "\n");
6858
6859 auto Remark = [&](OptimizationRemark OR) {
6860 LibFunc IsAllocShared;
6861 if (TLI->getLibFunc(*AI.CB, IsAllocShared))
6862 if (IsAllocShared == LibFunc___kmpc_alloc_shared)
6863 return OR << "Moving globalized variable to the stack.";
6864 return OR << "Moving memory allocation from the heap to the stack.";
6865 };
6866 if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
6867 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6868 else
6869 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6870
6871 const DataLayout &DL = A.getInfoCache().getDL();
6872 Value *Size;
6873 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6874 if (SizeAPI) {
6875 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6876 } else {
6877 LLVMContext &Ctx = AI.CB->getContext();
6878 ObjectSizeOpts Opts;
6879 ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
6880 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6881 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6882 cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());
6883 Size = SizeOffsetPair.Size;
6884 }
6885
6886 BasicBlock::iterator IP = AI.MoveAllocaIntoEntry
6887 ? F->getEntryBlock().begin()
6888 : AI.CB->getIterator();
6889
6890 Align Alignment(1);
6891 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6892 Alignment = std::max(Alignment, *RetAlign);
6893 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6894 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6895 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6896 "Expected an alignment during manifest!");
6897 Alignment =
6898 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6899 }
6900
6901 // TODO: Hoist the alloca towards the function entry.
6902 unsigned AS = DL.getAllocaAddrSpace();
6903 Instruction *Alloca =
6904 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6905 AI.CB->getName() + ".h2s", IP);
6906
6907 if (Alloca->getType() != AI.CB->getType())
6908 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6909 Alloca, AI.CB->getType(), "malloc_cast", AI.CB->getIterator());
6910
6911 auto *I8Ty = Type::getInt8Ty(F->getContext());
6912 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6913 assert(InitVal &&
6914 "Must be able to materialize initial memory state of allocation");
6915
6916 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6917
6918 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6919 auto *NBB = II->getNormalDest();
6920 BranchInst::Create(NBB, AI.CB->getParent());
6921 A.deleteAfterManifest(*AI.CB);
6922 } else {
6923 A.deleteAfterManifest(*AI.CB);
6924 }
6925
6926 // Initialize the alloca with the same value as used by the allocation
6927 // function. We can skip undef as the initial value of an alloc is
6928 // undef, and the memset would simply end up being DSEd.
6929 if (!isa<UndefValue>(InitVal)) {
6930 IRBuilder<> Builder(Alloca->getNextNode());
6931 // TODO: Use alignment above if align!=1
6932 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6933 }
6934 HasChanged = ChangeStatus::CHANGED;
6935 }
6936
6937 return HasChanged;
6938 }
6939
6940 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
6941 Value &V) {
6942 bool UsedAssumedInformation = false;
6943 std::optional<Constant *> SimpleV =
6944 A.getAssumedConstant(V, AA, UsedAssumedInformation);
6945 if (!SimpleV)
6946 return APInt(64, 0);
6947 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
6948 return CI->getValue();
6949 return std::nullopt;
6950 }
6951
6952 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
6953 AllocationInfo &AI) {
6954 auto Mapper = [&](const Value *V) -> const Value * {
6955 bool UsedAssumedInformation = false;
6956 if (std::optional<Constant *> SimpleV =
6957 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
6958 if (*SimpleV)
6959 return *SimpleV;
6960 return V;
6961 };
6962
6963 const Function *F = getAnchorScope();
6964 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6965 return getAllocSize(AI.CB, TLI, Mapper);
6966 }
6967
6968 /// Collection of all malloc-like calls in a function with associated
6969 /// information.
6970 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
6971
6972 /// Collection of all free-like calls in a function with associated
6973 /// information.
6974 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
6975
6976 ChangeStatus updateImpl(Attributor &A) override;
6977};
6978
6979ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
6981 const Function *F = getAnchorScope();
6982 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6983
6984 const auto *LivenessAA =
6985 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
6986
6987 MustBeExecutedContextExplorer *Explorer =
6988 A.getInfoCache().getMustBeExecutedContextExplorer();
6989
6990 bool StackIsAccessibleByOtherThreads =
6991 A.getInfoCache().stackIsAccessibleByOtherThreads();
6992
6993 LoopInfo *LI =
6994 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
6995 std::optional<bool> MayContainIrreducibleControl;
6996 auto IsInLoop = [&](BasicBlock &BB) {
6997 if (&F->getEntryBlock() == &BB)
6998 return false;
6999 if (!MayContainIrreducibleControl.has_value())
7000 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
7001 if (*MayContainIrreducibleControl)
7002 return true;
7003 if (!LI)
7004 return true;
7005 return LI->getLoopFor(&BB) != nullptr;
7006 };
7007
7008 // Flag to ensure we update our deallocation information at most once per
7009 // updateImpl call and only if we use the free check reasoning.
7010 bool HasUpdatedFrees = false;
7011
7012 auto UpdateFrees = [&]() {
7013 HasUpdatedFrees = true;
7014
7015 for (auto &It : DeallocationInfos) {
7016 DeallocationInfo &DI = *It.second;
7017 // For now we cannot use deallocations that have unknown inputs, skip
7018 // them.
7019 if (DI.MightFreeUnknownObjects)
7020 continue;
7021
7022 // No need to analyze dead calls, ignore them instead.
7023 bool UsedAssumedInformation = false;
7024 if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,
7025 /* CheckBBLivenessOnly */ true))
7026 continue;
7027
7028 // Use the non-optimistic version to get the freed object.
7029 Value *Obj = getUnderlyingObject(DI.FreedOp);
7030 if (!Obj) {
7031 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
7032 DI.MightFreeUnknownObjects = true;
7033 continue;
7034 }
7035
7036 // Free of null and undef can be ignored as no-ops (or UB in the latter
7037 // case).
7039 continue;
7040
7041 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
7042 if (!ObjCB) {
7043 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
7044 << "\n");
7045 DI.MightFreeUnknownObjects = true;
7046 continue;
7047 }
7048
7049 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7050 if (!AI) {
7051 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
7052 << "\n");
7053 DI.MightFreeUnknownObjects = true;
7054 continue;
7055 }
7056
7057 DI.PotentialAllocationCalls.insert(ObjCB);
7058 }
7059 };
7060
7061 auto FreeCheck = [&](AllocationInfo &AI) {
7062 // If the stack is not accessible by other threads, the "must-free" logic
7063 // doesn't apply as the pointer could be shared and needs to be places in
7064 // "shareable" memory.
7065 if (!StackIsAccessibleByOtherThreads) {
7066 bool IsKnownNoSycn;
7068 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {
7069 LLVM_DEBUG(
7070 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
7071 "other threads and function is not nosync:\n");
7072 return false;
7073 }
7074 }
7075 if (!HasUpdatedFrees)
7076 UpdateFrees();
7077
7078 // TODO: Allow multi exit functions that have different free calls.
7079 if (AI.PotentialFreeCalls.size() != 1) {
7080 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
7081 << AI.PotentialFreeCalls.size() << "\n");
7082 return false;
7083 }
7084 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7085 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7086 if (!DI) {
7087 LLVM_DEBUG(
7088 dbgs() << "[H2S] unique free call was not known as deallocation call "
7089 << *UniqueFree << "\n");
7090 return false;
7091 }
7092 if (DI->MightFreeUnknownObjects) {
7093 LLVM_DEBUG(
7094 dbgs() << "[H2S] unique free call might free unknown allocations\n");
7095 return false;
7096 }
7097 if (DI->PotentialAllocationCalls.empty())
7098 return true;
7099 if (DI->PotentialAllocationCalls.size() > 1) {
7100 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
7101 << DI->PotentialAllocationCalls.size()
7102 << " different allocations\n");
7103 return false;
7104 }
7105 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7106 LLVM_DEBUG(
7107 dbgs()
7108 << "[H2S] unique free call not known to free this allocation but "
7109 << **DI->PotentialAllocationCalls.begin() << "\n");
7110 return false;
7111 }
7112
7113 // __kmpc_alloc_shared and __kmpc_alloc_free are by construction matched.
7114 if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared) {
7115 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
7116 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7117 LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "
7118 "with the allocation "
7119 << *UniqueFree << "\n");
7120 return false;
7121 }
7122 }
7123 return true;
7124 };
7125
7126 auto UsesCheck = [&](AllocationInfo &AI) {
7127 bool ValidUsesOnly = true;
7128
7129 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7130 Instruction *UserI = cast<Instruction>(U.getUser());
7131 if (isa<LoadInst>(UserI))
7132 return true;
7133 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
7134 if (SI->getValueOperand() == U.get()) {
7136 << "[H2S] escaping store to memory: " << *UserI << "\n");
7137 ValidUsesOnly = false;
7138 } else {
7139 // A store into the malloc'ed memory is fine.
7140 }
7141 return true;
7142 }
7143 if (auto *CB = dyn_cast<CallBase>(UserI)) {
7144 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
7145 return true;
7146 if (DeallocationInfos.count(CB)) {
7147 AI.PotentialFreeCalls.insert(CB);
7148 return true;
7149 }
7150
7151 unsigned ArgNo = CB->getArgOperandNo(&U);
7152 auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);
7153
7154 bool IsKnownNoCapture;
7155 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7156 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);
7157
7158 // If a call site argument use is nofree, we are fine.
7159 bool IsKnownNoFree;
7160 bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
7161 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);
7162
7163 if (!IsAssumedNoCapture ||
7164 (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7165 !IsAssumedNoFree)) {
7166 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7167
7168 // Emit a missed remark if this is missed OpenMP globalization.
7169 auto Remark = [&](OptimizationRemarkMissed ORM) {
7170 return ORM
7171 << "Could not move globalized variable to the stack. "
7172 "Variable is potentially captured in call. Mark "
7173 "parameter as `__attribute__((noescape))` to override.";
7174 };
7175
7176 if (ValidUsesOnly &&
7177 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
7178 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
7179
7180 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
7181 ValidUsesOnly = false;
7182 }
7183 return true;
7184 }
7185
7186 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
7187 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
7188 Follow = true;
7189 return true;
7190 }
7191 // Unknown user for which we can not track uses further (in a way that
7192 // makes sense).
7193 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
7194 ValidUsesOnly = false;
7195 return true;
7196 };
7197 if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
7198 DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7199 [&](const Use &OldU, const Use &NewU) {
7200 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7201 return !SI || StackIsAccessibleByOtherThreads ||
7202 AA::isAssumedThreadLocalObject(
7203 A, *SI->getPointerOperand(), *this);
7204 }))
7205 return false;
7206 return ValidUsesOnly;
7207 };
7208
7209 // The actual update starts here. We look at all allocations and depending on
7210 // their status perform the appropriate check(s).
7211 for (auto &It : AllocationInfos) {
7212 AllocationInfo &AI = *It.second;
7213 if (AI.Status == AllocationInfo::INVALID)
7214 continue;
7215
7216 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7217 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7218 if (!APAlign) {
7219 // Can't generate an alloca which respects the required alignment
7220 // on the allocation.
7221 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7222 << "\n");
7223 AI.Status = AllocationInfo::INVALID;
7225 continue;
7226 }
7227 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7228 !APAlign->isPowerOf2()) {
7229 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7230 << "\n");
7231 AI.Status = AllocationInfo::INVALID;
7233 continue;
7234 }
7235 }
7236
7237 std::optional<APInt> Size = getSize(A, *this, AI);
7238 if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
7239 MaxHeapToStackSize != -1) {
7240 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7241 LLVM_DEBUG({
7242 if (!Size)
7243 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7244 else
7245 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7246 << MaxHeapToStackSize << "\n";
7247 });
7248
7249 AI.Status = AllocationInfo::INVALID;
7251 continue;
7252 }
7253 }
7254
7255 switch (AI.Status) {
7256 case AllocationInfo::STACK_DUE_TO_USE:
7257 if (UsesCheck(AI))
7258 break;
7259 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7260 [[fallthrough]];
7261 case AllocationInfo::STACK_DUE_TO_FREE:
7262 if (FreeCheck(AI))
7263 break;
7264 AI.Status = AllocationInfo::INVALID;
7266 break;
7267 case AllocationInfo::INVALID:
7268 llvm_unreachable("Invalid allocations should never reach this point!");
7269 };
7270
7271 // Check if we still think we can move it into the entry block. If the
7272 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7273 // ignore the potential compilations associated with loops.
7274 bool IsGlobalizedLocal =
7275 AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
7276 if (AI.MoveAllocaIntoEntry &&
7277 (!Size.has_value() ||
7278 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7279 AI.MoveAllocaIntoEntry = false;
7280 }
7281
7282 return Changed;
7283}
7284} // namespace
7285
7286/// ----------------------- Privatizable Pointers ------------------------------
7287namespace {
7288struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7289 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7290 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7291
7292 ChangeStatus indicatePessimisticFixpoint() override {
7293 AAPrivatizablePtr::indicatePessimisticFixpoint();
7294 PrivatizableType = nullptr;
7295 return ChangeStatus::CHANGED;
7296 }
7297
7298 /// Identify the type we can chose for a private copy of the underlying
7299 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7300 /// none.
7301 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7302
7303 /// Return a privatizable type that encloses both T0 and T1.
7304 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7305 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7306 std::optional<Type *> T1) {
7307 if (!T0)
7308 return T1;
7309 if (!T1)
7310 return T0;
7311 if (T0 == T1)
7312 return T0;
7313 return nullptr;
7314 }
7315
7316 std::optional<Type *> getPrivatizableType() const override {
7317 return PrivatizableType;
7318 }
7319
7320 const std::string getAsStr(Attributor *A) const override {
7321 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7322 }
7323
7324protected:
7325 std::optional<Type *> PrivatizableType;
7326};
7327
7328// TODO: Do this for call site arguments (probably also other values) as well.
7329
7330struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7331 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7332 : AAPrivatizablePtrImpl(IRP, A) {}
7333
7334 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7335 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7336 // If this is a byval argument and we know all the call sites (so we can
7337 // rewrite them), there is no need to check them explicitly.
7338 bool UsedAssumedInformation = false;
7340 A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,
7341 /* IgnoreSubsumingPositions */ true);
7342 if (!Attrs.empty() &&
7343 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7344 true, UsedAssumedInformation))
7345 return Attrs[0].getValueAsType();
7346
7347 std::optional<Type *> Ty;
7348 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7349
7350 // Make sure the associated call site argument has the same type at all call
7351 // sites and it is an allocation we know is safe to privatize, for now that
7352 // means we only allow alloca instructions.
7353 // TODO: We can additionally analyze the accesses in the callee to create
7354 // the type from that information instead. That is a little more
7355 // involved and will be done in a follow up patch.
7356 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7357 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7358 // Check if a coresponding argument was found or if it is one not
7359 // associated (which can happen for callback calls).
7360 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7361 return false;
7362
7363 // Check that all call sites agree on a type.
7364 auto *PrivCSArgAA =
7365 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7366 if (!PrivCSArgAA)
7367 return false;
7368 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7369
7370 LLVM_DEBUG({
7371 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7372 if (CSTy && *CSTy)
7373 (*CSTy)->print(dbgs());
7374 else if (CSTy)
7375 dbgs() << "<nullptr>";
7376 else
7377 dbgs() << "<none>";
7378 });
7379
7380 Ty = combineTypes(Ty, CSTy);
7381
7382 LLVM_DEBUG({
7383 dbgs() << " : New Type: ";
7384 if (Ty && *Ty)
7385 (*Ty)->print(dbgs());
7386 else if (Ty)
7387 dbgs() << "<nullptr>";
7388 else
7389 dbgs() << "<none>";
7390 dbgs() << "\n";
7391 });
7392
7393 return !Ty || *Ty;
7394 };
7395
7396 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7397 UsedAssumedInformation))
7398 return nullptr;
7399 return Ty;
7400 }
7401
7402 /// See AbstractAttribute::updateImpl(...).
7403 ChangeStatus updateImpl(Attributor &A) override {
7404 PrivatizableType = identifyPrivatizableType(A);
7405 if (!PrivatizableType)
7406 return ChangeStatus::UNCHANGED;
7407 if (!*PrivatizableType)
7408 return indicatePessimisticFixpoint();
7409
7410 // The dependence is optional so we don't give up once we give up on the
7411 // alignment.
7412 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7413 DepClassTy::OPTIONAL);
7414
7415 // Avoid arguments with padding for now.
7416 if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7417 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7418 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7419 return indicatePessimisticFixpoint();
7420 }
7421
7422 // Collect the types that will replace the privatizable type in the function
7423 // signature.
7424 SmallVector<Type *, 16> ReplacementTypes;
7425 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7426
7427 // Verify callee and caller agree on how the promoted argument would be
7428 // passed.
7429 Function &Fn = *getIRPosition().getAnchorScope();
7430 const auto *TTI =
7431 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7432 if (!TTI) {
7433 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7434 << Fn.getName() << "\n");
7435 return indicatePessimisticFixpoint();
7436 }
7437
7438 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7439 CallBase *CB = ACS.getInstruction();
7440 return TTI->areTypesABICompatible(
7441 CB->getCaller(),
7443 ReplacementTypes);
7444 };
7445 bool UsedAssumedInformation = false;
7446 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7447 UsedAssumedInformation)) {
7448 LLVM_DEBUG(
7449 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7450 << Fn.getName() << "\n");
7451 return indicatePessimisticFixpoint();
7452 }
7453
7454 // Register a rewrite of the argument.
7455 Argument *Arg = getAssociatedArgument();
7456 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7457 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7458 return indicatePessimisticFixpoint();
7459 }
7460
7461 unsigned ArgNo = Arg->getArgNo();
7462
7463 // Helper to check if for the given call site the associated argument is
7464 // passed to a callback where the privatization would be different.
7465 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7466 SmallVector<const Use *, 4> CallbackUses;
7467 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7468 for (const Use *U : CallbackUses) {
7469 AbstractCallSite CBACS(U);
7470 assert(CBACS && CBACS.isCallbackCall());
7471 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7472 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7473
7474 LLVM_DEBUG({
7475 dbgs()
7476 << "[AAPrivatizablePtr] Argument " << *Arg
7477 << "check if can be privatized in the context of its parent ("
7478 << Arg->getParent()->getName()
7479 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7480 "callback ("
7481 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7482 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7483 << CBACS.getCallArgOperand(CBArg) << " vs "
7484 << CB.getArgOperand(ArgNo) << "\n"
7485 << "[AAPrivatizablePtr] " << CBArg << " : "
7486 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7487 });
7488
7489 if (CBArgNo != int(ArgNo))
7490 continue;
7491 const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7492 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7493 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7494 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7495 if (!CBArgPrivTy)
7496 continue;
7497 if (*CBArgPrivTy == PrivatizableType)
7498 continue;
7499 }
7500
7501 LLVM_DEBUG({
7502 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7503 << " cannot be privatized in the context of its parent ("
7504 << Arg->getParent()->getName()
7505 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7506 "callback ("
7507 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7508 << ").\n[AAPrivatizablePtr] for which the argument "
7509 "privatization is not compatible.\n";
7510 });
7511 return false;
7512 }
7513 }
7514 return true;
7515 };
7516
7517 // Helper to check if for the given call site the associated argument is
7518 // passed to a direct call where the privatization would be different.
7519 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7520 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7521 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7522 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7523 "Expected a direct call operand for callback call operand");
7524
7525 Function *DCCallee =
7527 LLVM_DEBUG({
7528 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7529 << " check if be privatized in the context of its parent ("
7530 << Arg->getParent()->getName()
7531 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7532 "direct call of ("
7533 << DCArgNo << "@" << DCCallee->getName() << ").\n";
7534 });
7535
7536 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7537 const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7538 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7539 DepClassTy::REQUIRED);
7540 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7541 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7542 if (!DCArgPrivTy)
7543 return true;
7544 if (*DCArgPrivTy == PrivatizableType)
7545 return true;
7546 }
7547 }
7548
7549 LLVM_DEBUG({
7550 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7551 << " cannot be privatized in the context of its parent ("
7552 << Arg->getParent()->getName()
7553 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7554 "direct call of ("
7556 << ").\n[AAPrivatizablePtr] for which the argument "
7557 "privatization is not compatible.\n";
7558 });
7559 return false;
7560 };
7561
7562 // Helper to check if the associated argument is used at the given abstract
7563 // call site in a way that is incompatible with the privatization assumed
7564 // here.
7565 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7566 if (ACS.isDirectCall())
7567 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7568 if (ACS.isCallbackCall())
7569 return IsCompatiblePrivArgOfDirectCS(ACS);
7570 return false;
7571 };
7572
7573 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7574 UsedAssumedInformation))
7575 return indicatePessimisticFixpoint();
7576
7577 return ChangeStatus::UNCHANGED;
7578 }
7579
7580 /// Given a type to private \p PrivType, collect the constituates (which are
7581 /// used) in \p ReplacementTypes.
7582 static void
7583 identifyReplacementTypes(Type *PrivType,
7584 SmallVectorImpl<Type *> &ReplacementTypes) {
7585 // TODO: For now we expand the privatization type to the fullest which can
7586 // lead to dead arguments that need to be removed later.
7587 assert(PrivType && "Expected privatizable type!");
7588
7589 // Traverse the type, extract constituate types on the outermost level.
7590 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7591 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7592 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7593 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7594 ReplacementTypes.append(PrivArrayType->getNumElements(),
7595 PrivArrayType->getElementType());
7596 } else {
7597 ReplacementTypes.push_back(PrivType);
7598 }
7599 }
7600
7601 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7602 /// The values needed are taken from the arguments of \p F starting at
7603 /// position \p ArgNo.
7604 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7605 unsigned ArgNo, BasicBlock::iterator IP) {
7606 assert(PrivType && "Expected privatizable type!");
7607
7608 IRBuilder<NoFolder> IRB(IP->getParent(), IP);
7609 const DataLayout &DL = F.getDataLayout();
7610
7611 // Traverse the type, build GEPs and stores.
7612 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7613 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7614 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7615 Value *Ptr =
7616 constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
7617 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7618 }
7619 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7620 Type *PointeeTy = PrivArrayType->getElementType();
7621 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7622 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7623 Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
7624 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7625 }
7626 } else {
7627 new StoreInst(F.getArg(ArgNo), &Base, IP);
7628 }
7629 }
7630
7631 /// Extract values from \p Base according to the type \p PrivType at the
7632 /// call position \p ACS. The values are appended to \p ReplacementValues.
7633 void createReplacementValues(Align Alignment, Type *PrivType,
7634 AbstractCallSite ACS, Value *Base,
7635 SmallVectorImpl<Value *> &ReplacementValues) {
7636 assert(Base && "Expected base value!");
7637 assert(PrivType && "Expected privatizable type!");
7638 Instruction *IP = ACS.getInstruction();
7639
7640 IRBuilder<NoFolder> IRB(IP);
7641 const DataLayout &DL = IP->getDataLayout();
7642
7643 // Traverse the type, build GEPs and loads.
7644 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7645 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7646 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7647 Type *PointeeTy = PrivStructType->getElementType(u);
7648 Value *Ptr =
7649 constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
7650 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7651 L->setAlignment(Alignment);
7652 ReplacementValues.push_back(L);
7653 }
7654 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7655 Type *PointeeTy = PrivArrayType->getElementType();
7656 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7657 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7658 Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
7659 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7660 L->setAlignment(Alignment);
7661 ReplacementValues.push_back(L);
7662 }
7663 } else {
7664 LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
7665 L->setAlignment(Alignment);
7666 ReplacementValues.push_back(L);
7667 }
7668 }
7669
7670 /// See AbstractAttribute::manifest(...)
7671 ChangeStatus manifest(Attributor &A) override {
7672 if (!PrivatizableType)
7673 return ChangeStatus::UNCHANGED;
7674 assert(*PrivatizableType && "Expected privatizable type!");
7675
7676 // Collect all tail calls in the function as we cannot allow new allocas to
7677 // escape into tail recursion.
7678 // TODO: Be smarter about new allocas escaping into tail calls.
7680 bool UsedAssumedInformation = false;
7681 if (!A.checkForAllInstructions(
7682 [&](Instruction &I) {
7683 CallInst &CI = cast<CallInst>(I);
7684 if (CI.isTailCall())
7685 TailCalls.push_back(&CI);
7686 return true;
7687 },
7688 *this, {Instruction::Call}, UsedAssumedInformation))
7689 return ChangeStatus::UNCHANGED;
7690
7691 Argument *Arg = getAssociatedArgument();
7692 // Query AAAlign attribute for alignment of associated argument to
7693 // determine the best alignment of loads.
7694 const auto *AlignAA =
7695 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7696
7697 // Callback to repair the associated function. A new alloca is placed at the
7698 // beginning and initialized with the values passed through arguments. The
7699 // new alloca replaces the use of the old pointer argument.
7701 [=](const Attributor::ArgumentReplacementInfo &ARI,
7702 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7703 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7705 const DataLayout &DL = IP->getDataLayout();
7706 unsigned AS = DL.getAllocaAddrSpace();
7707 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7708 Arg->getName() + ".priv", IP);
7709 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7710 ArgIt->getArgNo(), IP);
7711
7712 if (AI->getType() != Arg->getType())
7713 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7714 AI, Arg->getType(), "", IP);
7715 Arg->replaceAllUsesWith(AI);
7716
7717 for (CallInst *CI : TailCalls)
7718 CI->setTailCall(false);
7719 };
7720
7721 // Callback to repair a call site of the associated function. The elements
7722 // of the privatizable type are loaded prior to the call and passed to the
7723 // new function version.
7725 [=](const Attributor::ArgumentReplacementInfo &ARI,
7726 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7727 // When no alignment is specified for the load instruction,
7728 // natural alignment is assumed.
7729 createReplacementValues(
7730 AlignAA ? AlignAA->getAssumedAlign() : Align(0),
7731 *PrivatizableType, ACS,
7732 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7733 NewArgOperands);
7734 };
7735
7736 // Collect the types that will replace the privatizable type in the function
7737 // signature.
7738 SmallVector<Type *, 16> ReplacementTypes;
7739 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7740
7741 // Register a rewrite of the argument.
7742 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7743 std::move(FnRepairCB),
7744 std::move(ACSRepairCB)))
7745 return ChangeStatus::CHANGED;
7746 return ChangeStatus::UNCHANGED;
7747 }
7748
7749 /// See AbstractAttribute::trackStatistics()
7750 void trackStatistics() const override {
7751 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7752 }
7753};
7754
7755struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7756 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7757 : AAPrivatizablePtrImpl(IRP, A) {}
7758
7759 /// See AbstractAttribute::initialize(...).
7760 void initialize(Attributor &A) override {
7761 // TODO: We can privatize more than arguments.
7762 indicatePessimisticFixpoint();
7763 }
7764
7765 ChangeStatus updateImpl(Attributor &A) override {
7766 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7767 "updateImpl will not be called");
7768 }
7769
7770 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7771 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7772 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7773 if (!Obj) {
7774 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7775 return nullptr;
7776 }
7777
7778 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7779 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7780 if (CI->isOne())
7781 return AI->getAllocatedType();
7782 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7783 auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7784 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7785 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7786 return PrivArgAA->getPrivatizableType();
7787 }
7788
7789 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7790 "alloca nor privatizable argument: "
7791 << *Obj << "!\n");
7792 return nullptr;
7793 }
7794
7795 /// See AbstractAttribute::trackStatistics()
7796 void trackStatistics() const override {
7797 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7798 }
7799};
7800
7801struct AAPrivatizablePtrCallSiteArgument final
7802 : public AAPrivatizablePtrFloating {
7803 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7804 : AAPrivatizablePtrFloating(IRP, A) {}
7805
7806 /// See AbstractAttribute::initialize(...).
7807 void initialize(Attributor &A) override {
7808 if (A.hasAttr(getIRPosition(), Attribute::ByVal))
7809 indicateOptimisticFixpoint();
7810 }
7811
7812 /// See AbstractAttribute::updateImpl(...).
7813 ChangeStatus updateImpl(Attributor &A) override {
7814 PrivatizableType = identifyPrivatizableType(A);
7815 if (!PrivatizableType)
7816 return ChangeStatus::UNCHANGED;
7817 if (!*PrivatizableType)
7818 return indicatePessimisticFixpoint();
7819
7820 const IRPosition &IRP = getIRPosition();
7821 bool IsKnownNoCapture;
7822 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7823 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7824 if (!IsAssumedNoCapture) {
7825 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7826 return indicatePessimisticFixpoint();
7827 }
7828
7829 bool IsKnownNoAlias;
7831 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7832 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7833 return indicatePessimisticFixpoint();
7834 }
7835
7836 bool IsKnown;
7837 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7838 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7839 return indicatePessimisticFixpoint();
7840 }
7841
7842 return ChangeStatus::UNCHANGED;
7843 }
7844
7845 /// See AbstractAttribute::trackStatistics()
7846 void trackStatistics() const override {
7847 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7848 }
7849};
7850
7851struct AAPrivatizablePtrCallSiteReturned final
7852 : public AAPrivatizablePtrFloating {
7853 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7854 : AAPrivatizablePtrFloating(IRP, A) {}
7855
7856 /// See AbstractAttribute::initialize(...).
7857 void initialize(Attributor &A) override {
7858 // TODO: We can privatize more than arguments.
7859 indicatePessimisticFixpoint();
7860 }
7861
7862 /// See AbstractAttribute::trackStatistics()
7863 void trackStatistics() const override {
7864 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7865 }
7866};
7867
7868struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7869 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7870 : AAPrivatizablePtrFloating(IRP, A) {}
7871
7872 /// See AbstractAttribute::initialize(...).
7873 void initialize(Attributor &A) override {
7874 // TODO: We can privatize more than arguments.
7875 indicatePessimisticFixpoint();
7876 }
7877
7878 /// See AbstractAttribute::trackStatistics()
7879 void trackStatistics() const override {
7880 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7881 }
7882};
7883} // namespace
7884
7885/// -------------------- Memory Behavior Attributes ----------------------------
7886/// Includes read-none, read-only, and write-only.
7887/// ----------------------------------------------------------------------------
7888namespace {
7889struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7890 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7891 : AAMemoryBehavior(IRP, A) {}
7892
7893 /// See AbstractAttribute::initialize(...).
7894 void initialize(Attributor &A) override {
7895 intersectAssumedBits(BEST_STATE);
7896 getKnownStateFromValue(A, getIRPosition(), getState());
7897 AAMemoryBehavior::initialize(A);
7898 }
7899
7900 /// Return the memory behavior information encoded in the IR for \p IRP.
7901 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
7902 BitIntegerState &State,
7903 bool IgnoreSubsumingPositions = false) {
7905 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7906 for (const Attribute &Attr : Attrs) {
7907 switch (Attr.getKindAsEnum()) {
7908 case Attribute::ReadNone:
7909 State.addKnownBits(NO_ACCESSES);
7910 break;
7911 case Attribute::ReadOnly:
7912 State.addKnownBits(NO_WRITES);
7913 break;
7914 case Attribute::WriteOnly:
7915 State.addKnownBits(NO_READS);
7916 break;
7917 default:
7918 llvm_unreachable("Unexpected attribute!");
7919 }
7920 }
7921
7922 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7923 if (!I->mayReadFromMemory())
7924 State.addKnownBits(NO_READS);
7925 if (!I->mayWriteToMemory())
7926 State.addKnownBits(NO_WRITES);
7927 }
7928 }
7929
7930 /// See AbstractAttribute::getDeducedAttributes(...).
7931 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7932 SmallVectorImpl<Attribute> &Attrs) const override {
7933 assert(Attrs.size() == 0);
7934 if (isAssumedReadNone())
7935 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7936 else if (isAssumedReadOnly())
7937 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7938 else if (isAssumedWriteOnly())
7939 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
7940 assert(Attrs.size() <= 1);
7941 }
7942
7943 /// See AbstractAttribute::manifest(...).
7944 ChangeStatus manifest(Attributor &A) override {
7945 const IRPosition &IRP = getIRPosition();
7946
7947 if (A.hasAttr(IRP, Attribute::ReadNone,
7948 /* IgnoreSubsumingPositions */ true))
7949 return ChangeStatus::UNCHANGED;
7950
7951 // Check if we would improve the existing attributes first.
7952 SmallVector<Attribute, 4> DeducedAttrs;
7953 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
7954 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
7955 return A.hasAttr(IRP, Attr.getKindAsEnum(),
7956 /* IgnoreSubsumingPositions */ true);
7957 }))
7958 return ChangeStatus::UNCHANGED;
7959
7960 // Clear existing attributes.
7961 A.removeAttrs(IRP, AttrKinds);
7962 // Clear conflicting writable attribute.
7963 if (isAssumedReadOnly())
7964 A.removeAttrs(IRP, Attribute::Writable);
7965
7966 // Use the generic manifest method.
7967 return IRAttribute::manifest(A);
7968 }
7969
7970 /// See AbstractState::getAsStr().
7971 const std::string getAsStr(Attributor *A) const override {
7972 if (isAssumedReadNone())
7973 return "readnone";
7974 if (isAssumedReadOnly())
7975 return "readonly";
7976 if (isAssumedWriteOnly())
7977 return "writeonly";
7978 return "may-read/write";
7979 }
7980
7981 /// The set of IR attributes AAMemoryBehavior deals with.
7982 static const Attribute::AttrKind AttrKinds[3];
7983};
7984
7985const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
7986 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
7987
7988/// Memory behavior attribute for a floating value.
7989struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
7990 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
7991 : AAMemoryBehaviorImpl(IRP, A) {}
7992
7993 /// See AbstractAttribute::updateImpl(...).
7994 ChangeStatus updateImpl(Attributor &A) override;
7995
7996 /// See AbstractAttribute::trackStatistics()
7997 void trackStatistics() const override {
7998 if (isAssumedReadNone())
8000 else if (isAssumedReadOnly())
8002 else if (isAssumedWriteOnly())
8004 }
8005
8006private:
8007 /// Return true if users of \p UserI might access the underlying
8008 /// variable/location described by \p U and should therefore be analyzed.
8009 bool followUsersOfUseIn(Attributor &A, const Use &U,
8010 const Instruction *UserI);
8011
8012 /// Update the state according to the effect of use \p U in \p UserI.
8013 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
8014};
8015
8016/// Memory behavior attribute for function argument.
8017struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8018 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
8019 : AAMemoryBehaviorFloating(IRP, A) {}
8020
8021 /// See AbstractAttribute::initialize(...).
8022 void initialize(Attributor &A) override {
8023 intersectAssumedBits(BEST_STATE);
8024 const IRPosition &IRP = getIRPosition();
8025 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
8026 // can query it when we use has/getAttr. That would allow us to reuse the
8027 // initialize of the base class here.
8028 bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
8029 /* IgnoreSubsumingPositions */ true);
8030 getKnownStateFromValue(A, IRP, getState(),
8031 /* IgnoreSubsumingPositions */ HasByVal);
8032 }
8033
8034 ChangeStatus manifest(Attributor &A) override {
8035 // TODO: Pointer arguments are not supported on vectors of pointers yet.
8036 if (!getAssociatedValue().getType()->isPointerTy())
8037 return ChangeStatus::UNCHANGED;
8038
8039 // TODO: From readattrs.ll: "inalloca parameters are always
8040 // considered written"
8041 if (A.hasAttr(getIRPosition(),
8042 {Attribute::InAlloca, Attribute::Preallocated})) {
8043 removeKnownBits(NO_WRITES);
8044 removeAssumedBits(NO_WRITES);
8045 }
8046 A.removeAttrs(getIRPosition(), AttrKinds);
8047 return AAMemoryBehaviorFloating::manifest(A);
8048 }
8049
8050 /// See AbstractAttribute::trackStatistics()
8051 void trackStatistics() const override {
8052 if (isAssumedReadNone())
8053 STATS_DECLTRACK_ARG_ATTR(readnone)
8054 else if (isAssumedReadOnly())
8055 STATS_DECLTRACK_ARG_ATTR(readonly)
8056 else if (isAssumedWriteOnly())
8057 STATS_DECLTRACK_ARG_ATTR(writeonly)
8058 }
8059};
8060
8061struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8062 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
8063 : AAMemoryBehaviorArgument(IRP, A) {}
8064
8065 /// See AbstractAttribute::initialize(...).
8066 void initialize(Attributor &A) override {
8067 // If we don't have an associated attribute this is either a variadic call
8068 // or an indirect call, either way, nothing to do here.
8069 Argument *Arg = getAssociatedArgument();
8070 if (!Arg) {
8071 indicatePessimisticFixpoint();
8072 return;
8073 }
8074 if (Arg->hasByValAttr()) {
8075 addKnownBits(NO_WRITES);
8076 removeKnownBits(NO_READS);
8077 removeAssumedBits(NO_READS);
8078 }
8079 AAMemoryBehaviorArgument::initialize(A);
8080 if (getAssociatedFunction()->isDeclaration())
8081 indicatePessimisticFixpoint();
8082 }
8083
8084 /// See AbstractAttribute::updateImpl(...).
8085 ChangeStatus updateImpl(Attributor &A) override {
8086 // TODO: Once we have call site specific value information we can provide
8087 // call site specific liveness liveness information and then it makes
8088 // sense to specialize attributes for call sites arguments instead of
8089 // redirecting requests to the callee argument.
8090 Argument *Arg = getAssociatedArgument();
8091 const IRPosition &ArgPos = IRPosition::argument(*Arg);
8092 auto *ArgAA =
8093 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
8094 if (!ArgAA)
8095 return indicatePessimisticFixpoint();
8096 return clampStateAndIndicateChange(getState(), ArgAA->getState());
8097 }
8098
8099 /// See AbstractAttribute::trackStatistics()
8100 void trackStatistics() const override {
8101 if (isAssumedReadNone())
8103 else if (isAssumedReadOnly())
8105 else if (isAssumedWriteOnly())
8107 }
8108};
8109
8110/// Memory behavior attribute for a call site return position.
8111struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8112 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8113 : AAMemoryBehaviorFloating(IRP, A) {}
8114
8115 /// See AbstractAttribute::initialize(...).
8116 void initialize(Attributor &A) override {
8117 AAMemoryBehaviorImpl::initialize(A);
8118 }
8119 /// See AbstractAttribute::manifest(...).
8120 ChangeStatus manifest(Attributor &A) override {
8121 // We do not annotate returned values.
8122 return ChangeStatus::UNCHANGED;
8123 }
8124
8125 /// See AbstractAttribute::trackStatistics()
8126 void trackStatistics() const override {}
8127};
8128
8129/// An AA to represent the memory behavior function attributes.
8130struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8131 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8132 : AAMemoryBehaviorImpl(IRP, A) {}
8133
8134 /// See AbstractAttribute::updateImpl(Attributor &A).
8135 ChangeStatus updateImpl(Attributor &A) override;
8136
8137 /// See AbstractAttribute::manifest(...).
8138 ChangeStatus manifest(Attributor &A) override {
8139 // TODO: It would be better to merge this with AAMemoryLocation, so that
8140 // we could determine read/write per location. This would also have the
8141 // benefit of only one place trying to manifest the memory attribute.
8142 Function &F = cast<Function>(getAnchorValue());
8144 if (isAssumedReadNone())
8145 ME = MemoryEffects::none();
8146 else if (isAssumedReadOnly())
8148 else if (isAssumedWriteOnly())
8150
8151 A.removeAttrs(getIRPosition(), AttrKinds);
8152 // Clear conflicting writable attribute.
8153 if (ME.onlyReadsMemory())
8154 for (Argument &Arg : F.args())
8155 A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);
8156 return A.manifestAttrs(getIRPosition(),
8157 Attribute::getWithMemoryEffects(F.getContext(), ME));
8158 }
8159
8160 /// See AbstractAttribute::trackStatistics()
8161 void trackStatistics() const override {
8162 if (isAssumedReadNone())
8163 STATS_DECLTRACK_FN_ATTR(readnone)
8164 else if (isAssumedReadOnly())
8165 STATS_DECLTRACK_FN_ATTR(readonly)
8166 else if (isAssumedWriteOnly())
8167 STATS_DECLTRACK_FN_ATTR(writeonly)
8168 }
8169};
8170
8171/// AAMemoryBehavior attribute for call sites.
8172struct AAMemoryBehaviorCallSite final
8173 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8174 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8175 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8176
8177 /// See AbstractAttribute::manifest(...).
8178 ChangeStatus manifest(Attributor &A) override {
8179 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8180 CallBase &CB = cast<CallBase>(getAnchorValue());
8182 if (isAssumedReadNone())
8183 ME = MemoryEffects::none();
8184 else if (isAssumedReadOnly())
8186 else if (isAssumedWriteOnly())
8188
8189 A.removeAttrs(getIRPosition(), AttrKinds);
8190 // Clear conflicting writable attribute.
8191 if (ME.onlyReadsMemory())
8192 for (Use &U : CB.args())
8193 A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),
8194 Attribute::Writable);
8195 return A.manifestAttrs(
8196 getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
8197 }
8198
8199 /// See AbstractAttribute::trackStatistics()
8200 void trackStatistics() const override {
8201 if (isAssumedReadNone())
8202 STATS_DECLTRACK_CS_ATTR(readnone)
8203 else if (isAssumedReadOnly())
8204 STATS_DECLTRACK_CS_ATTR(readonly)
8205 else if (isAssumedWriteOnly())
8206 STATS_DECLTRACK_CS_ATTR(writeonly)
8207 }
8208};
8209
8210ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8211
8212 // The current assumed state used to determine a change.
8213 auto AssumedState = getAssumed();
8214
8215 auto CheckRWInst = [&](Instruction &I) {
8216 // If the instruction has an own memory behavior state, use it to restrict
8217 // the local state. No further analysis is required as the other memory
8218 // state is as optimistic as it gets.
8219 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8220 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8222 if (MemBehaviorAA) {
8223 intersectAssumedBits(MemBehaviorAA->getAssumed());
8224 return !isAtFixpoint();
8225 }
8226 }
8227
8228 // Remove access kind modifiers if necessary.
8229 if (I.mayReadFromMemory())
8230 removeAssumedBits(NO_READS);
8231 if (I.mayWriteToMemory())
8232 removeAssumedBits(NO_WRITES);
8233 return !isAtFixpoint();
8234 };
8235
8236 bool UsedAssumedInformation = false;
8237 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8238 UsedAssumedInformation))
8239 return indicatePessimisticFixpoint();
8240
8241 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8243}
8244
8245ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8246
8247 const IRPosition &IRP = getIRPosition();
8248 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8249 AAMemoryBehavior::StateType &S = getState();
8250
8251 // First, check the function scope. We take the known information and we avoid
8252 // work if the assumed information implies the current assumed information for
8253 // this attribute. This is a valid for all but byval arguments.
8254 Argument *Arg = IRP.getAssociatedArgument();
8255 AAMemoryBehavior::base_t FnMemAssumedState =
8257 if (!Arg || !Arg->hasByValAttr()) {
8258 const auto *FnMemAA =
8259 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8260 if (FnMemAA) {
8261 FnMemAssumedState = FnMemAA->getAssumed();
8262 S.addKnownBits(FnMemAA->getKnown());
8263 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8265 }
8266 }
8267
8268 // The current assumed state used to determine a change.
8269 auto AssumedState = S.getAssumed();
8270
8271 // Make sure the value is not captured (except through "return"), if
8272 // it is, any information derived would be irrelevant anyway as we cannot
8273 // check the potential aliases introduced by the capture. However, no need
8274 // to fall back to anythign less optimistic than the function state.
8275 bool IsKnownNoCapture;
8276 const AANoCapture *ArgNoCaptureAA = nullptr;
8277 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8278 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
8279 &ArgNoCaptureAA);
8280
8281 if (!IsAssumedNoCapture &&
8282 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8283 S.intersectAssumedBits(FnMemAssumedState);
8284 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8286 }
8287
8288 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8289 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8290 Instruction *UserI = cast<Instruction>(U.getUser());
8291 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8292 << " \n");
8293
8294 // Droppable users, e.g., llvm::assume does not actually perform any action.
8295 if (UserI->isDroppable())
8296 return true;
8297
8298 // Check if the users of UserI should also be visited.
8299 Follow = followUsersOfUseIn(A, U, UserI);
8300
8301 // If UserI might touch memory we analyze the use in detail.
8302 if (UserI->mayReadOrWriteMemory())
8303 analyzeUseIn(A, U, UserI);
8304
8305 return !isAtFixpoint();
8306 };
8307
8308 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8309 return indicatePessimisticFixpoint();
8310
8311 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8313}
8314
8315bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8316 const Instruction *UserI) {
8317 // The loaded value is unrelated to the pointer argument, no need to
8318 // follow the users of the load.
8319 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8320 return false;
8321
8322 // By default we follow all uses assuming UserI might leak information on U,
8323 // we have special handling for call sites operands though.
8324 const auto *CB = dyn_cast<CallBase>(UserI);
8325 if (!CB || !CB->isArgOperand(&U))
8326 return true;
8327
8328 // If the use is a call argument known not to be captured, the users of
8329 // the call do not need to be visited because they have to be unrelated to
8330 // the input. Note that this check is not trivial even though we disallow
8331 // general capturing of the underlying argument. The reason is that the
8332 // call might the argument "through return", which we allow and for which we
8333 // need to check call users.
8334 if (U.get()->getType()->isPointerTy()) {
8335 unsigned ArgNo = CB->getArgOperandNo(&U);
8336 bool IsKnownNoCapture;
8338 A, this, IRPosition::callsite_argument(*CB, ArgNo),
8339 DepClassTy::OPTIONAL, IsKnownNoCapture);
8340 }
8341
8342 return true;
8343}
8344
8345void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8346 const Instruction *UserI) {
8347 assert(UserI->mayReadOrWriteMemory());
8348
8349 switch (UserI->getOpcode()) {
8350 default:
8351 // TODO: Handle all atomics and other side-effect operations we know of.
8352 break;
8353 case Instruction::Load:
8354 // Loads cause the NO_READS property to disappear.
8355 removeAssumedBits(NO_READS);
8356 return;
8357
8358 case Instruction::Store:
8359 // Stores cause the NO_WRITES property to disappear if the use is the
8360 // pointer operand. Note that while capturing was taken care of somewhere
8361 // else we need to deal with stores of the value that is not looked through.
8362 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8363 removeAssumedBits(NO_WRITES);
8364 else
8365 indicatePessimisticFixpoint();
8366 return;
8367
8368 case Instruction::Call:
8369 case Instruction::CallBr:
8370 case Instruction::Invoke: {
8371 // For call sites we look at the argument memory behavior attribute (this
8372 // could be recursive!) in order to restrict our own state.
8373 const auto *CB = cast<CallBase>(UserI);
8374
8375 // Give up on operand bundles.
8376 if (CB->isBundleOperand(&U)) {
8377 indicatePessimisticFixpoint();
8378 return;
8379 }
8380
8381 // Calling a function does read the function pointer, maybe write it if the
8382 // function is self-modifying.
8383 if (CB->isCallee(&U)) {
8384 removeAssumedBits(NO_READS);
8385 break;
8386 }
8387
8388 // Adjust the possible access behavior based on the information on the
8389 // argument.
8390 IRPosition Pos;
8391 if (U.get()->getType()->isPointerTy())
8393 else
8395 const auto *MemBehaviorAA =
8396 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8397 if (!MemBehaviorAA)
8398 break;
8399 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8400 // and at least "known".
8401 intersectAssumedBits(MemBehaviorAA->getAssumed());
8402 return;
8403 }
8404 };
8405
8406 // Generally, look at the "may-properties" and adjust the assumed state if we
8407 // did not trigger special handling before.
8408 if (UserI->mayReadFromMemory())
8409 removeAssumedBits(NO_READS);
8410 if (UserI->mayWriteToMemory())
8411 removeAssumedBits(NO_WRITES);
8412}
8413} // namespace
8414
8415/// -------------------- Memory Locations Attributes ---------------------------
8416/// Includes read-none, argmemonly, inaccessiblememonly,
8417/// inaccessiblememorargmemonly
8418/// ----------------------------------------------------------------------------
8419
8422 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8423 return "all memory";
8425 return "no memory";
8426 std::string S = "memory:";
8427 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8428 S += "stack,";
8429 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8430 S += "constant,";
8432 S += "internal global,";
8434 S += "external global,";
8435 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8436 S += "argument,";
8438 S += "inaccessible,";
8439 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8440 S += "malloced,";
8441 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8442 S += "unknown,";
8443 S.pop_back();
8444 return S;
8445}
8446
8447namespace {
8448struct AAMemoryLocationImpl : public AAMemoryLocation {
8449
8450 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8451 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8452 AccessKind2Accesses.fill(nullptr);
8453 }
8454
8455 ~AAMemoryLocationImpl() override {
8456 // The AccessSets are allocated via a BumpPtrAllocator, we call
8457 // the destructor manually.
8458 for (AccessSet *AS : AccessKind2Accesses)
8459 if (AS)
8460 AS->~AccessSet();
8461 }
8462
8463 /// See AbstractAttribute::initialize(...).
8464 void initialize(Attributor &A) override {
8465 intersectAssumedBits(BEST_STATE);
8466 getKnownStateFromValue(A, getIRPosition(), getState());
8467 AAMemoryLocation::initialize(A);
8468 }
8469
8470 /// Return the memory behavior information encoded in the IR for \p IRP.
8471 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8472 BitIntegerState &State,
8473 bool IgnoreSubsumingPositions = false) {
8474 // For internal functions we ignore `argmemonly` and
8475 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8476 // constant propagation. It is unclear if this is the best way but it is
8477 // unlikely this will cause real performance problems. If we are deriving
8478 // attributes for the anchor function we even remove the attribute in
8479 // addition to ignoring it.
8480 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8481 // MemoryEffects::Other as a possible location.
8482 bool UseArgMemOnly = true;
8483 Function *AnchorFn = IRP.getAnchorScope();
8484 if (AnchorFn && A.isRunOn(*AnchorFn))
8485 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8486
8488 A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8489 for (const Attribute &Attr : Attrs) {
8490 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8491 MemoryEffects ME = Attr.getMemoryEffects();
8492 if (ME.doesNotAccessMemory()) {
8493 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8494 continue;
8495 }
8496 if (ME.onlyAccessesInaccessibleMem()) {
8497 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8498 continue;
8499 }
8500 if (ME.onlyAccessesArgPointees()) {
8501 if (UseArgMemOnly)
8502 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8503 else {
8504 // Remove location information, only keep read/write info.
8505 ME = MemoryEffects(ME.getModRef());
8506 A.manifestAttrs(IRP,
8507 Attribute::getWithMemoryEffects(
8508 IRP.getAnchorValue().getContext(), ME),
8509 /*ForceReplace*/ true);
8510 }
8511 continue;
8512 }
8514 if (UseArgMemOnly)
8515 State.addKnownBits(inverseLocation(
8516 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8517 else {
8518 // Remove location information, only keep read/write info.
8519 ME = MemoryEffects(ME.getModRef());
8520 A.manifestAttrs(IRP,
8521 Attribute::getWithMemoryEffects(
8522 IRP.getAnchorValue().getContext(), ME),
8523 /*ForceReplace*/ true);
8524 }
8525 continue;
8526 }
8527 }
8528 }
8529
8530 /// See AbstractAttribute::getDeducedAttributes(...).
8531 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8532 SmallVectorImpl<Attribute> &Attrs) const override {
8533 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8534 assert(Attrs.size() == 0);
8535 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8536 if (isAssumedReadNone())
8537 Attrs.push_back(
8538 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8539 else if (isAssumedInaccessibleMemOnly())
8540 Attrs.push_back(Attribute::getWithMemoryEffects(
8542 else if (isAssumedArgMemOnly())
8543 Attrs.push_back(
8544 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8545 else if (isAssumedInaccessibleOrArgMemOnly())
8546 Attrs.push_back(Attribute::getWithMemoryEffects(
8548 }
8549 assert(Attrs.size() <= 1);
8550 }
8551
8552 /// See AbstractAttribute::manifest(...).
8553 ChangeStatus manifest(Attributor &A) override {
8554 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8555 // provide per-location modref information here.
8556 const IRPosition &IRP = getIRPosition();
8557
8558 SmallVector<Attribute, 1> DeducedAttrs;
8559 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8560 if (DeducedAttrs.size() != 1)
8561 return ChangeStatus::UNCHANGED;
8562 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8563
8564 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8565 IRP.getAnchorValue().getContext(), ME));
8566 }
8567
8568 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
8569 bool checkForAllAccessesToMemoryKind(
8570 function_ref<bool(const Instruction *, const Value *, AccessKind,
8571 MemoryLocationsKind)>
8572 Pred,
8573 MemoryLocationsKind RequestedMLK) const override {
8574 if (!isValidState())
8575 return false;
8576
8577 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8578 if (AssumedMLK == NO_LOCATIONS)
8579 return true;
8580
8581 unsigned Idx = 0;
8582 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8583 CurMLK *= 2, ++Idx) {
8584 if (CurMLK & RequestedMLK)
8585 continue;
8586
8587 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8588 for (const AccessInfo &AI : *Accesses)
8589 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8590 return false;
8591 }
8592
8593 return true;
8594 }
8595
8596 ChangeStatus indicatePessimisticFixpoint() override {
8597 // If we give up and indicate a pessimistic fixpoint this instruction will
8598 // become an access for all potential access kinds:
8599 // TODO: Add pointers for argmemonly and globals to improve the results of
8600 // checkForAllAccessesToMemoryKind.
8601 bool Changed = false;
8602 MemoryLocationsKind KnownMLK = getKnown();
8603 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8604 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8605 if (!(CurMLK & KnownMLK))
8606 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8607 getAccessKindFromInst(I));
8608 return AAMemoryLocation::indicatePessimisticFixpoint();
8609 }
8610
8611protected:
8612 /// Helper struct to tie together an instruction that has a read or write
8613 /// effect with the pointer it accesses (if any).
8614 struct AccessInfo {
8615
8616 /// The instruction that caused the access.
8617 const Instruction *I;
8618
8619 /// The base pointer that is accessed, or null if unknown.
8620 const Value *Ptr;
8621
8622 /// The kind of access (read/write/read+write).
8624
8625 bool operator==(const AccessInfo &RHS) const {
8626 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8627 }
8628 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8629 if (LHS.I != RHS.I)
8630 return LHS.I < RHS.I;
8631 if (LHS.Ptr != RHS.Ptr)
8632 return LHS.Ptr < RHS.Ptr;
8633 if (LHS.Kind != RHS.Kind)
8634 return LHS.Kind < RHS.Kind;
8635 return false;
8636 }
8637 };
8638
8639 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8640 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8641 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8642 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8643 AccessKind2Accesses;
8644
8645 /// Categorize the pointer arguments of CB that might access memory in
8646 /// AccessedLoc and update the state and access map accordingly.
8647 void
8648 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8649 AAMemoryLocation::StateType &AccessedLocs,
8650 bool &Changed);
8651
8652 /// Return the kind(s) of location that may be accessed by \p V.
8654 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8655
8656 /// Return the access kind as determined by \p I.
8657 AccessKind getAccessKindFromInst(const Instruction *I) {
8658 AccessKind AK = READ_WRITE;
8659 if (I) {
8660 AK = I->mayReadFromMemory() ? READ : NONE;
8661 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8662 }
8663 return AK;
8664 }
8665
8666 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8667 /// an access of kind \p AK to a \p MLK memory location with the access
8668 /// pointer \p Ptr.
8669 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8670 MemoryLocationsKind MLK, const Instruction *I,
8671 const Value *Ptr, bool &Changed,
8672 AccessKind AK = READ_WRITE) {
8673
8674 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8675 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8676 if (!Accesses)
8677 Accesses = new (Allocator) AccessSet();
8678 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8679 if (MLK == NO_UNKOWN_MEM)
8680 MLK = NO_LOCATIONS;
8681 State.removeAssumedBits(MLK);
8682 }
8683
8684 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8685 /// arguments, and update the state and access map accordingly.
8686 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8687 AAMemoryLocation::StateType &State, bool &Changed,
8688 unsigned AccessAS = 0);
8689
8690 /// Used to allocate access sets.
8692};
8693
8694void AAMemoryLocationImpl::categorizePtrValue(
8695 Attributor &A, const Instruction &I, const Value &Ptr,
8696 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8697 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8698 << Ptr << " ["
8699 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8700
8701 auto Pred = [&](Value &Obj) {
8702 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8703 // TODO: recognize the TBAA used for constant accesses.
8704 MemoryLocationsKind MLK = NO_LOCATIONS;
8705
8706 // Filter accesses to constant (GPU) memory if we have an AS at the access
8707 // site or the object is known to actually have the associated AS.
8708 if ((AccessAS == (unsigned)AA::GPUAddressSpace::Constant ||
8709 (ObjectAS == (unsigned)AA::GPUAddressSpace::Constant &&
8710 isIdentifiedObject(&Obj))) &&
8711 AA::isGPU(*I.getModule()))
8712 return true;
8713
8714 if (isa<UndefValue>(&Obj))
8715 return true;
8716 if (isa<Argument>(&Obj)) {
8717 // TODO: For now we do not treat byval arguments as local copies performed
8718 // on the call edge, though, we should. To make that happen we need to
8719 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8720 // would also allow us to mark functions only accessing byval arguments as
8721 // readnone again, arguably their accesses have no effect outside of the
8722 // function, like accesses to allocas.
8723 MLK = NO_ARGUMENT_MEM;
8724 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8725 // Reading constant memory is not treated as a read "effect" by the
8726 // function attr pass so we won't neither. Constants defined by TBAA are
8727 // similar. (We know we do not write it because it is constant.)
8728 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8729 if (GVar->isConstant())
8730 return true;
8731
8732 if (GV->hasLocalLinkage())
8733 MLK = NO_GLOBAL_INTERNAL_MEM;
8734 else
8735 MLK = NO_GLOBAL_EXTERNAL_MEM;
8736 } else if (isa<ConstantPointerNull>(&Obj) &&
8737 (!NullPointerIsDefined(getAssociatedFunction(), AccessAS) ||
8738 !NullPointerIsDefined(getAssociatedFunction(), ObjectAS))) {
8739 return true;
8740 } else if (isa<AllocaInst>(&Obj)) {
8741 MLK = NO_LOCAL_MEM;
8742 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8743 bool IsKnownNoAlias;
8746 IsKnownNoAlias))
8747 MLK = NO_MALLOCED_MEM;
8748 else
8749 MLK = NO_UNKOWN_MEM;
8750 } else {
8751 MLK = NO_UNKOWN_MEM;
8752 }
8753
8754 assert(MLK != NO_LOCATIONS && "No location specified!");
8755 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8756 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8757 updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
8758 getAccessKindFromInst(&I));
8759
8760 return true;
8761 };
8762
8763 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8765 if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8766 LLVM_DEBUG(
8767 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8768 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8769 getAccessKindFromInst(&I));
8770 return;
8771 }
8772
8773 LLVM_DEBUG(
8774 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8775 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8776}
8777
8778void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8779 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8780 bool &Changed) {
8781 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8782
8783 // Skip non-pointer arguments.
8784 const Value *ArgOp = CB.getArgOperand(ArgNo);
8785 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8786 continue;
8787
8788 // Skip readnone arguments.
8789 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8790 const auto *ArgOpMemLocationAA =
8791 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8792
8793 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8794 continue;
8795
8796 // Categorize potentially accessed pointer arguments as if there was an
8797 // access instruction with them as pointer.
8798 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8799 }
8800}
8801
8803AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8804 bool &Changed) {
8805 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8806 << I << "\n");
8807
8808 AAMemoryLocation::StateType AccessedLocs;
8809 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8810
8811 if (auto *CB = dyn_cast<CallBase>(&I)) {
8812
8813 // First check if we assume any memory is access is visible.
8814 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8816 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8817 << " [" << CBMemLocationAA << "]\n");
8818 if (!CBMemLocationAA) {
8819 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
8820 Changed, getAccessKindFromInst(&I));
8821 return NO_UNKOWN_MEM;
8822 }
8823
8824 if (CBMemLocationAA->isAssumedReadNone())
8825 return NO_LOCATIONS;
8826
8827 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8828 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8829 Changed, getAccessKindFromInst(&I));
8830 return AccessedLocs.getAssumed();
8831 }
8832
8833 uint32_t CBAssumedNotAccessedLocs =
8834 CBMemLocationAA->getAssumedNotAccessedLocation();
8835
8836 // Set the argmemonly and global bit as we handle them separately below.
8837 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8838 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8839
8840 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8841 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8842 continue;
8843 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8844 getAccessKindFromInst(&I));
8845 }
8846
8847 // Now handle global memory if it might be accessed. This is slightly tricky
8848 // as NO_GLOBAL_MEM has multiple bits set.
8849 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8850 if (HasGlobalAccesses) {
8851 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8852 AccessKind Kind, MemoryLocationsKind MLK) {
8853 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8854 getAccessKindFromInst(&I));
8855 return true;
8856 };
8857 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8858 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8859 return AccessedLocs.getWorstState();
8860 }
8861
8862 LLVM_DEBUG(
8863 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8864 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8865
8866 // Now handle argument memory if it might be accessed.
8867 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8868 if (HasArgAccesses)
8869 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8870
8871 LLVM_DEBUG(
8872 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8873 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8874
8875 return AccessedLocs.getAssumed();
8876 }
8877
8878 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8879 LLVM_DEBUG(
8880 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8881 << I << " [" << *Ptr << "]\n");
8882 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
8883 Ptr->getType()->getPointerAddressSpace());
8884 return AccessedLocs.getAssumed();
8885 }
8886
8887 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8888 << I << "\n");
8889 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8890 getAccessKindFromInst(&I));
8891 return AccessedLocs.getAssumed();
8892}
8893
8894/// An AA to represent the memory behavior function attributes.
8895struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8896 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8897 : AAMemoryLocationImpl(IRP, A) {}
8898
8899 /// See AbstractAttribute::updateImpl(Attributor &A).
8900 ChangeStatus updateImpl(Attributor &A) override {
8901
8902 const auto *MemBehaviorAA =
8903 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8904 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8905 if (MemBehaviorAA->isKnownReadNone())
8906 return indicateOptimisticFixpoint();
8908 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8909 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8910 return ChangeStatus::UNCHANGED;
8911 }
8912
8913 // The current assumed state used to determine a change.
8914 auto AssumedState = getAssumed();
8915 bool Changed = false;
8916
8917 auto CheckRWInst = [&](Instruction &I) {
8918 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8919 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8920 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8921 removeAssumedBits(inverseLocation(MLK, false, false));
8922 // Stop once only the valid bit set in the *not assumed location*, thus
8923 // once we don't actually exclude any memory locations in the state.
8924 return getAssumedNotAccessedLocation() != VALID_STATE;
8925 };
8926
8927 bool UsedAssumedInformation = false;
8928 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8929 UsedAssumedInformation))
8930 return indicatePessimisticFixpoint();
8931
8932 Changed |= AssumedState != getAssumed();
8933 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8934 }
8935
8936 /// See AbstractAttribute::trackStatistics()
8937 void trackStatistics() const override {
8938 if (isAssumedReadNone())
8939 STATS_DECLTRACK_FN_ATTR(readnone)
8940 else if (isAssumedArgMemOnly())
8941 STATS_DECLTRACK_FN_ATTR(argmemonly)
8942 else if (isAssumedInaccessibleMemOnly())
8943 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
8944 else if (isAssumedInaccessibleOrArgMemOnly())
8945 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
8946 }
8947};
8948
8949/// AAMemoryLocation attribute for call sites.
8950struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
8951 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
8952 : AAMemoryLocationImpl(IRP, A) {}
8953
8954 /// See AbstractAttribute::updateImpl(...).
8955 ChangeStatus updateImpl(Attributor &A) override {
8956 // TODO: Once we have call site specific value information we can provide
8957 // call site specific liveness liveness information and then it makes
8958 // sense to specialize attributes for call sites arguments instead of
8959 // redirecting requests to the callee argument.
8960 Function *F = getAssociatedFunction();
8961 const IRPosition &FnPos = IRPosition::function(*F);
8962 auto *FnAA =
8963 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
8964 if (!FnAA)
8965 return indicatePessimisticFixpoint();
8966 bool Changed = false;
8967 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
8968 AccessKind Kind, MemoryLocationsKind MLK) {
8969 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
8970 getAccessKindFromInst(I));
8971 return true;
8972 };
8973 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
8974 return indicatePessimisticFixpoint();
8975 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8976 }
8977
8978 /// See AbstractAttribute::trackStatistics()
8979 void trackStatistics() const override {
8980 if (isAssumedReadNone())
8981 STATS_DECLTRACK_CS_ATTR(readnone)
8982 }
8983};
8984} // namespace
8985
8986/// ------------------ denormal-fp-math Attribute -------------------------
8987
8988namespace {
8989struct AADenormalFPMathImpl : public AADenormalFPMath {
8990 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
8991 : AADenormalFPMath(IRP, A) {}
8992
8993 const std::string getAsStr(Attributor *A) const override {
8994 std::string Str("AADenormalFPMath[");
8995 raw_string_ostream OS(Str);
8996
8997 DenormalState Known = getKnown();
8998 if (Known.Mode.isValid())
8999 OS << "denormal-fp-math=" << Known.Mode;
9000 else
9001 OS << "invalid";
9002
9003 if (Known.ModeF32.isValid())
9004 OS << " denormal-fp-math-f32=" << Known.ModeF32;
9005 OS << ']';
9006 return Str;
9007 }
9008};
9009
9010struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9011 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
9012 : AADenormalFPMathImpl(IRP, A) {}
9013
9014 void initialize(Attributor &A) override {
9015 const Function *F = getAnchorScope();
9016 DenormalMode Mode = F->getDenormalModeRaw();
9017 DenormalMode ModeF32 = F->getDenormalModeF32Raw();
9018
9019 // TODO: Handling this here prevents handling the case where a callee has a
9020 // fixed denormal-fp-math with dynamic denormal-fp-math-f32, but called from
9021 // a function with a fully fixed mode.
9022 if (ModeF32 == DenormalMode::getInvalid())
9023 ModeF32 = Mode;
9024 Known = DenormalState{Mode, ModeF32};
9025 if (isModeFixed())
9026 indicateFixpoint();
9027 }
9028
9029 ChangeStatus updateImpl(Attributor &A) override {
9030 ChangeStatus Change = ChangeStatus::UNCHANGED;
9031
9032 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
9033 Function *Caller = CS.getInstruction()->getFunction();
9034 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
9035 << "->" << getAssociatedFunction()->getName() << '\n');
9036
9037 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
9038 *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
9039 if (!CallerInfo)
9040 return false;
9041
9042 Change = Change | clampStateAndIndicateChange(this->getState(),
9043 CallerInfo->getState());
9044 return true;
9045 };
9046
9047 bool AllCallSitesKnown = true;
9048 if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))
9049 return indicatePessimisticFixpoint();
9050
9051 if (Change == ChangeStatus::CHANGED && isModeFixed())
9052 indicateFixpoint();
9053 return Change;
9054 }
9055
9056 ChangeStatus manifest(Attributor &A) override {
9057 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9058
9059 SmallVector<Attribute, 2> AttrToAdd;
9060 SmallVector<StringRef, 2> AttrToRemove;
9061 if (Known.Mode == DenormalMode::getDefault()) {
9062 AttrToRemove.push_back("denormal-fp-math");
9063 } else {
9064 AttrToAdd.push_back(
9065 Attribute::get(Ctx, "denormal-fp-math", Known.Mode.str()));
9066 }
9067
9068 if (Known.ModeF32 != Known.Mode) {
9069 AttrToAdd.push_back(
9070 Attribute::get(Ctx, "denormal-fp-math-f32", Known.ModeF32.str()));
9071 } else {
9072 AttrToRemove.push_back("denormal-fp-math-f32");
9073 }
9074
9075 auto &IRP = getIRPosition();
9076
9077 // TODO: There should be a combined add and remove API.
9078 return A.removeAttrs(IRP, AttrToRemove) |
9079 A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);
9080 }
9081
9082 void trackStatistics() const override {
9083 STATS_DECLTRACK_FN_ATTR(denormal_fp_math)
9084 }
9085};
9086} // namespace
9087
9088/// ------------------ Value Constant Range Attribute -------------------------
9089
9090namespace {
9091struct AAValueConstantRangeImpl : AAValueConstantRange {
9092 using StateType = IntegerRangeState;
9093 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
9094 : AAValueConstantRange(IRP, A) {}
9095
9096 /// See AbstractAttribute::initialize(..).
9097 void initialize(Attributor &A) override {
9098 if (A.hasSimplificationCallback(getIRPosition())) {
9099 indicatePessimisticFixpoint();
9100 return;
9101 }
9102
9103 // Intersect a range given by SCEV.
9104 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
9105
9106 // Intersect a range given by LVI.
9107 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
9108 }
9109
9110 /// See AbstractAttribute::getAsStr().
9111 const std::string getAsStr(Attributor *A) const override {
9112 std::string Str;
9113 llvm::raw_string_ostream OS(Str);
9114 OS << "range(" << getBitWidth() << ")<";
9115 getKnown().print(OS);
9116 OS << " / ";
9117 getAssumed().print(OS);
9118 OS << ">";
9119 return Str;
9120 }
9121
9122 /// Helper function to get a SCEV expr for the associated value at program
9123 /// point \p I.
9124 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
9125 if (!getAnchorScope())
9126 return nullptr;
9127
9128 ScalarEvolution *SE =
9129 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9130 *getAnchorScope());
9131
9132 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9133 *getAnchorScope());
9134
9135 if (!SE || !LI)
9136 return nullptr;
9137
9138 const SCEV *S = SE->getSCEV(&getAssociatedValue());
9139 if (!I)
9140 return S;
9141
9142 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
9143 }
9144
9145 /// Helper function to get a range from SCEV for the associated value at
9146 /// program point \p I.
9147 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9148 const Instruction *I = nullptr) const {
9149 if (!getAnchorScope())
9150 return getWorstState(getBitWidth());
9151
9152 ScalarEvolution *SE =
9153 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9154 *getAnchorScope());
9155
9156 const SCEV *S = getSCEV(A, I);
9157 if (!SE || !S)
9158 return getWorstState(getBitWidth());
9159
9160 return SE->getUnsignedRange(S);
9161 }
9162
9163 /// Helper function to get a range from LVI for the associated value at
9164 /// program point \p I.
9165 ConstantRange
9166 getConstantRangeFromLVI(Attributor &A,
9167 const Instruction *CtxI = nullptr) const {
9168 if (!getAnchorScope())
9169 return getWorstState(getBitWidth());
9170
9171 LazyValueInfo *LVI =
9172 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9173 *getAnchorScope());
9174
9175 if (!LVI || !CtxI)
9176 return getWorstState(getBitWidth());
9177 return LVI->getConstantRange(&getAssociatedValue(),
9178 const_cast<Instruction *>(CtxI),
9179 /*UndefAllowed*/ false);
9180 }
9181
9182 /// Return true if \p CtxI is valid for querying outside analyses.
9183 /// This basically makes sure we do not ask intra-procedural analysis
9184 /// about a context in the wrong function or a context that violates
9185 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9186 /// if the original context of this AA is OK or should be considered invalid.
9187 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9188 const Instruction *CtxI,
9189 bool AllowAACtxI) const {
9190 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9191 return false;
9192
9193 // Our context might be in a different function, neither intra-procedural
9194 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9195 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9196 return false;
9197
9198 // If the context is not dominated by the value there are paths to the
9199 // context that do not define the value. This cannot be handled by
9200 // LazyValueInfo so we need to bail.
9201 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9202 InformationCache &InfoCache = A.getInfoCache();
9203 const DominatorTree *DT =
9204 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9205 *I->getFunction());
9206 return DT && DT->dominates(I, CtxI);
9207 }
9208
9209 return true;
9210 }
9211
9212 /// See AAValueConstantRange::getKnownConstantRange(..).
9213 ConstantRange
9214 getKnownConstantRange(Attributor &A,
9215 const Instruction *CtxI = nullptr) const override {
9216 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9217 /* AllowAACtxI */ false))
9218 return getKnown();
9219
9220 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9221 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9222 return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
9223 }
9224
9225 /// See AAValueConstantRange::getAssumedConstantRange(..).
9226 ConstantRange
9227 getAssumedConstantRange(Attributor &A,
9228 const Instruction *CtxI = nullptr) const override {
9229 // TODO: Make SCEV use Attributor assumption.
9230 // We may be able to bound a variable range via assumptions in
9231 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9232 // evolve to x^2 + x, then we can say that y is in [2, 12].
9233 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9234 /* AllowAACtxI */ false))
9235 return getAssumed();
9236
9237 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9238 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9239 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9240 }
9241
9242 /// Helper function to create MDNode for range metadata.
9243 static MDNode *
9244 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9245 const ConstantRange &AssumedConstantRange) {
9246 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9247 Ty, AssumedConstantRange.getLower())),
9248 ConstantAsMetadata::get(ConstantInt::get(
9249 Ty, AssumedConstantRange.getUpper()))};
9250 return MDNode::get(Ctx, LowAndHigh);
9251 }
9252
9253 /// Return true if \p Assumed is included in ranges from instruction \p I.
9254 static bool isBetterRange(const ConstantRange &Assumed,
9255 const Instruction &I) {
9256 if (Assumed.isFullSet())
9257 return false;
9258
9259 std::optional<ConstantRange> Known;
9260
9261 if (const auto *CB = dyn_cast<CallBase>(&I)) {
9262 Known = CB->getRange();
9263 } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
9264 // If multiple ranges are annotated in IR, we give up to annotate assumed
9265 // range for now.
9266
9267 // TODO: If there exists a known range which containts assumed range, we
9268 // can say assumed range is better.
9269 if (KnownRanges->getNumOperands() > 2)
9270 return false;
9271
9272 ConstantInt *Lower =
9273 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9274 ConstantInt *Upper =
9275 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9276
9277 Known.emplace(Lower->getValue(), Upper->getValue());
9278 }
9279 return !Known || (*Known != Assumed && Known->contains(Assumed));
9280 }
9281
9282 /// Helper function to set range metadata.
9283 static bool
9284 setRangeMetadataIfisBetterRange(Instruction *I,
9285 const ConstantRange &AssumedConstantRange) {
9286 if (isBetterRange(AssumedConstantRange, *I)) {
9287 I->setMetadata(LLVMContext::MD_range,
9288 getMDNodeForConstantRange(I->getType(), I->getContext(),
9289 AssumedConstantRange));
9290 return true;
9291 }
9292 return false;
9293 }
9294 /// Helper function to set range return attribute.
9295 static bool
9296 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9297 Instruction *I,
9298 const ConstantRange &AssumedConstantRange) {
9299 if (isBetterRange(AssumedConstantRange, *I)) {
9300 A.manifestAttrs(IRP,
9301 Attribute::get(I->getContext(), Attribute::Range,
9302 AssumedConstantRange),
9303 /*ForceReplace*/ true);
9304 return true;
9305 }
9306 return false;
9307 }
9308
9309 /// See AbstractAttribute::manifest()
9310 ChangeStatus manifest(Attributor &A) override {
9311 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9312 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9313 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9314
9315 auto &V = getAssociatedValue();
9316 if (!AssumedConstantRange.isEmptySet() &&
9317 !AssumedConstantRange.isSingleElement()) {
9318 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9319 assert(I == getCtxI() && "Should not annotate an instruction which is "
9320 "not the context instruction");
9321 if (isa<LoadInst>(I))
9322 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9323 Changed = ChangeStatus::CHANGED;
9324 if (isa<CallInst>(I))
9325 if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
9326 AssumedConstantRange))
9327 Changed = ChangeStatus::CHANGED;
9328 }
9329 }
9330
9331 return Changed;
9332 }
9333};
9334
9335struct AAValueConstantRangeArgument final
9336 : AAArgumentFromCallSiteArguments<
9337 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9338 true /* BridgeCallBaseContext */> {
9339 using Base = AAArgumentFromCallSiteArguments<
9340 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9341 true /* BridgeCallBaseContext */>;
9342 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9343 : Base(IRP, A) {}
9344
9345 /// See AbstractAttribute::trackStatistics()
9346 void trackStatistics() const override {
9347 STATS_DECLTRACK_ARG_ATTR(value_range)
9348 }
9349};
9350
9351struct AAValueConstantRangeReturned
9352 : AAReturnedFromReturnedValues<AAValueConstantRange,
9353 AAValueConstantRangeImpl,
9354 AAValueConstantRangeImpl::StateType,
9355 /* PropagateCallBaseContext */ true> {
9356 using Base =
9357 AAReturnedFromReturnedValues<AAValueConstantRange,
9358 AAValueConstantRangeImpl,
9359 AAValueConstantRangeImpl::StateType,
9360 /* PropagateCallBaseContext */ true>;
9361 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9362 : Base(IRP, A) {}
9363
9364 /// See AbstractAttribute::initialize(...).
9365 void initialize(Attributor &A) override {
9366 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9367 indicatePessimisticFixpoint();
9368 }
9369
9370 /// See AbstractAttribute::trackStatistics()
9371 void trackStatistics() const override {
9372 STATS_DECLTRACK_FNRET_ATTR(value_range)
9373 }
9374};
9375
9376struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9377 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9378 : AAValueConstantRangeImpl(IRP, A) {}
9379
9380 /// See AbstractAttribute::initialize(...).
9381 void initialize(Attributor &A) override {
9382 AAValueConstantRangeImpl::initialize(A);
9383 if (isAtFixpoint())
9384 return;
9385
9386 Value &V = getAssociatedValue();
9387
9388 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9389 unionAssumed(ConstantRange(C->getValue()));
9390 indicateOptimisticFixpoint();
9391 return;
9392 }
9393
9394 if (isa<UndefValue>(&V)) {
9395 // Collapse the undef state to 0.
9396 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9397 indicateOptimisticFixpoint();
9398 return;
9399 }
9400
9401 if (isa<CallBase>(&V))
9402 return;
9403
9404 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9405 return;
9406
9407 // If it is a load instruction with range metadata, use it.
9408 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9409 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9410 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9411 return;
9412 }
9413
9414 // We can work with PHI and select instruction as we traverse their operands
9415 // during update.
9416 if (isa<SelectInst>(V) || isa<PHINode>(V))
9417 return;
9418
9419 // Otherwise we give up.
9420 indicatePessimisticFixpoint();
9421
9422 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9423 << getAssociatedValue() << "\n");
9424 }
9425
9426 bool calculateBinaryOperator(
9427 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9428 const Instruction *CtxI,
9429 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9430 Value *LHS = BinOp->getOperand(0);
9431 Value *RHS = BinOp->getOperand(1);
9432
9433 // Simplify the operands first.
9434 bool UsedAssumedInformation = false;
9435 const auto &SimplifiedLHS = A.getAssumedSimplified(
9436 IRPosition::value(*LHS, getCallBaseContext()), *this,
9437 UsedAssumedInformation, AA::Interprocedural);
9438 if (!SimplifiedLHS.has_value())
9439 return true;
9440 if (!*SimplifiedLHS)
9441 return false;
9442 LHS = *SimplifiedLHS;
9443
9444 const auto &SimplifiedRHS = A.getAssumedSimplified(
9445 IRPosition::value(*RHS, getCallBaseContext()), *this,
9446 UsedAssumedInformation, AA::Interprocedural);
9447 if (!SimplifiedRHS.has_value())
9448 return true;
9449 if (!*SimplifiedRHS)
9450 return false;
9451 RHS = *SimplifiedRHS;
9452
9453 // TODO: Allow non integers as well.
9454 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9455 return false;
9456
9457 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9458 *this, IRPosition::value(*LHS, getCallBaseContext()),
9459 DepClassTy::REQUIRED);
9460 if (!LHSAA)
9461 return false;
9462 QuerriedAAs.push_back(LHSAA);
9463 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9464
9465 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9466 *this, IRPosition::value(*RHS, getCallBaseContext()),
9467 DepClassTy::REQUIRED);
9468 if (!RHSAA)
9469 return false;
9470 QuerriedAAs.push_back(RHSAA);
9471 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9472
9473 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9474
9475 T.unionAssumed(AssumedRange);
9476
9477 // TODO: Track a known state too.
9478
9479 return T.isValidState();
9480 }
9481
9482 bool calculateCastInst(
9483 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9484 const Instruction *CtxI,
9485 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9486 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9487 // TODO: Allow non integers as well.
9488 Value *OpV = CastI->getOperand(0);
9489
9490 // Simplify the operand first.
9491 bool UsedAssumedInformation = false;
9492 const auto &SimplifiedOpV = A.getAssumedSimplified(
9493 IRPosition::value(*OpV, getCallBaseContext()), *this,
9494 UsedAssumedInformation, AA::Interprocedural);
9495 if (!SimplifiedOpV.has_value())
9496 return true;
9497 if (!*SimplifiedOpV)
9498 return false;
9499 OpV = *SimplifiedOpV;
9500
9501 if (!OpV->getType()->isIntegerTy())
9502 return false;
9503
9504 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9505 *this, IRPosition::value(*OpV, getCallBaseContext()),
9506 DepClassTy::REQUIRED);
9507 if (!OpAA)
9508 return false;
9509 QuerriedAAs.push_back(OpAA);
9510 T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
9511 getState().getBitWidth()));
9512 return T.isValidState();
9513 }
9514
9515 bool
9516 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9517 const Instruction *CtxI,
9518 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9519 Value *LHS = CmpI->getOperand(0);
9520 Value *RHS = CmpI->getOperand(1);
9521
9522 // Simplify the operands first.
9523 bool UsedAssumedInformation = false;
9524 const auto &SimplifiedLHS = A.getAssumedSimplified(
9525 IRPosition::value(*LHS, getCallBaseContext()), *this,
9526 UsedAssumedInformation, AA::Interprocedural);
9527 if (!SimplifiedLHS.has_value())
9528 return true;
9529 if (!*SimplifiedLHS)
9530 return false;
9531 LHS = *SimplifiedLHS;
9532
9533 const auto &SimplifiedRHS = A.getAssumedSimplified(
9534 IRPosition::value(*RHS, getCallBaseContext()), *this,
9535 UsedAssumedInformation, AA::Interprocedural);
9536 if (!SimplifiedRHS.has_value())
9537 return true;
9538 if (!*SimplifiedRHS)
9539 return false;
9540 RHS = *SimplifiedRHS;
9541
9542 // TODO: Allow non integers as well.
9543 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9544 return false;
9545
9546 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9547 *this, IRPosition::value(*LHS, getCallBaseContext()),
9548 DepClassTy::REQUIRED);
9549 if (!LHSAA)
9550 return false;
9551 QuerriedAAs.push_back(LHSAA);
9552 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9553 *this, IRPosition::value(*RHS, getCallBaseContext()),
9554 DepClassTy::REQUIRED);
9555 if (!RHSAA)
9556 return false;
9557 QuerriedAAs.push_back(RHSAA);
9558 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9559 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9560
9561 // If one of them is empty set, we can't decide.
9562 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9563 return true;
9564
9565 bool MustTrue = false, MustFalse = false;
9566
9567 auto AllowedRegion =
9569
9570 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9571 MustFalse = true;
9572
9573 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9574 MustTrue = true;
9575
9576 assert((!MustTrue || !MustFalse) &&
9577 "Either MustTrue or MustFalse should be false!");
9578
9579 if (MustTrue)
9580 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9581 else if (MustFalse)
9582 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9583 else
9584 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9585
9586 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9587 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9588 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9589 << *RHSAA);
9590
9591 // TODO: Track a known state too.
9592 return T.isValidState();
9593 }
9594
9595 /// See AbstractAttribute::updateImpl(...).
9596 ChangeStatus updateImpl(Attributor &A) override {
9597
9598 IntegerRangeState T(getBitWidth());
9599 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9601 if (!I || isa<CallBase>(I)) {
9602
9603 // Simplify the operand first.
9604 bool UsedAssumedInformation = false;
9605 const auto &SimplifiedOpV = A.getAssumedSimplified(
9606 IRPosition::value(V, getCallBaseContext()), *this,
9607 UsedAssumedInformation, AA::Interprocedural);
9608 if (!SimplifiedOpV.has_value())
9609 return true;
9610 if (!*SimplifiedOpV)
9611 return false;
9612 Value *VPtr = *SimplifiedOpV;
9613
9614 // If the value is not instruction, we query AA to Attributor.
9615 const auto *AA = A.getAAFor<AAValueConstantRange>(
9616 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9617 DepClassTy::REQUIRED);
9618
9619 // Clamp operator is not used to utilize a program point CtxI.
9620 if (AA)
9621 T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
9622 else
9623 return false;
9624
9625 return T.isValidState();
9626 }
9627
9629 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9630 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9631 return false;
9632 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9633 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9634 return false;
9635 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9636 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9637 return false;
9638 } else {
9639 // Give up with other instructions.
9640 // TODO: Add other instructions
9641
9642 T.indicatePessimisticFixpoint();
9643 return false;
9644 }
9645
9646 // Catch circular reasoning in a pessimistic way for now.
9647 // TODO: Check how the range evolves and if we stripped anything, see also
9648 // AADereferenceable or AAAlign for similar situations.
9649 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9650 if (QueriedAA != this)
9651 continue;
9652 // If we are in a stady state we do not need to worry.
9653 if (T.getAssumed() == getState().getAssumed())
9654 continue;
9655 T.indicatePessimisticFixpoint();
9656 }
9657
9658 return T.isValidState();
9659 };
9660
9661 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9662 return indicatePessimisticFixpoint();
9663
9664 // Ensure that long def-use chains can't cause circular reasoning either by
9665 // introducing a cutoff below.
9666 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9667 return ChangeStatus::UNCHANGED;
9668 if (++NumChanges > MaxNumChanges) {
9669 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9670 << " but only " << MaxNumChanges
9671 << " are allowed to avoid cyclic reasoning.");
9672 return indicatePessimisticFixpoint();
9673 }
9674 return ChangeStatus::CHANGED;
9675 }
9676
9677 /// See AbstractAttribute::trackStatistics()
9678 void trackStatistics() const override {
9680 }
9681
9682 /// Tracker to bail after too many widening steps of the constant range.
9683 int NumChanges = 0;
9684
9685 /// Upper bound for the number of allowed changes (=widening steps) for the
9686 /// constant range before we give up.
9687 static constexpr int MaxNumChanges = 5;
9688};
9689
9690struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9691 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9692 : AAValueConstantRangeImpl(IRP, A) {}
9693
9694 /// See AbstractAttribute::initialize(...).
9695 ChangeStatus updateImpl(Attributor &A) override {
9696 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9697 "not be called");
9698 }
9699
9700 /// See AbstractAttribute::trackStatistics()
9701 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9702};
9703
9704struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9705 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9706 : AAValueConstantRangeFunction(IRP, A) {}
9707
9708 /// See AbstractAttribute::trackStatistics()
9709 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9710};
9711
9712struct AAValueConstantRangeCallSiteReturned
9713 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9714 AAValueConstantRangeImpl::StateType,
9715 /* IntroduceCallBaseContext */ true> {
9716 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9717 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9718 AAValueConstantRangeImpl::StateType,
9719 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9720
9721 /// See AbstractAttribute::initialize(...).
9722 void initialize(Attributor &A) override {
9723 // If it is a call instruction with range attribute, use the range.
9724 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
9725 if (std::optional<ConstantRange> Range = CI->getRange())
9726 intersectKnown(*Range);
9727 }
9728
9729 AAValueConstantRangeImpl::initialize(A);
9730 }
9731
9732 /// See AbstractAttribute::trackStatistics()
9733 void trackStatistics() const override {
9734 STATS_DECLTRACK_CSRET_ATTR(value_range)
9735 }
9736};
9737struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9738 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9739 : AAValueConstantRangeFloating(IRP, A) {}
9740
9741 /// See AbstractAttribute::manifest()
9742 ChangeStatus manifest(Attributor &A) override {
9743 return ChangeStatus::UNCHANGED;
9744 }
9745
9746 /// See AbstractAttribute::trackStatistics()
9747 void trackStatistics() const override {
9748 STATS_DECLTRACK_CSARG_ATTR(value_range)
9749 }
9750};
9751} // namespace
9752
9753/// ------------------ Potential Values Attribute -------------------------
9754
9755namespace {
9756struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9757 using StateType = PotentialConstantIntValuesState;
9758
9759 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9760 : AAPotentialConstantValues(IRP, A) {}
9761
9762 /// See AbstractAttribute::initialize(..).
9763 void initialize(Attributor &A) override {
9764 if (A.hasSimplificationCallback(getIRPosition()))
9765 indicatePessimisticFixpoint();
9766 else
9767 AAPotentialConstantValues::initialize(A);
9768 }
9769
9770 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9771 bool &ContainsUndef, bool ForSelf) {
9773 bool UsedAssumedInformation = false;
9774 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9775 UsedAssumedInformation)) {
9776 // Avoid recursion when the caller is computing constant values for this
9777 // IRP itself.
9778 if (ForSelf)
9779 return false;
9780 if (!IRP.getAssociatedType()->isIntegerTy())
9781 return false;
9782 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9783 *this, IRP, DepClassTy::REQUIRED);
9784 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9785 return false;
9786 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9787 S = PotentialValuesAA->getState().getAssumedSet();
9788 return true;
9789 }
9790
9791 // Copy all the constant values, except UndefValue. ContainsUndef is true
9792 // iff Values contains only UndefValue instances. If there are other known
9793 // constants, then UndefValue is dropped.
9794 ContainsUndef = false;
9795 for (auto &It : Values) {
9796 if (isa<UndefValue>(It.getValue())) {
9797 ContainsUndef = true;
9798 continue;
9799 }
9800 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9801 if (!CI)
9802 return false;
9803 S.insert(CI->getValue());
9804 }
9805 ContainsUndef &= S.empty();
9806
9807 return true;
9808 }
9809
9810 /// See AbstractAttribute::getAsStr().
9811 const std::string getAsStr(Attributor *A) const override {
9812 std::string Str;
9813 llvm::raw_string_ostream OS(Str);
9814 OS << getState();
9815 return Str;
9816 }
9817
9818 /// See AbstractAttribute::updateImpl(...).
9819 ChangeStatus updateImpl(Attributor &A) override {
9820 return indicatePessimisticFixpoint();
9821 }
9822};
9823
9824struct AAPotentialConstantValuesArgument final
9825 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9826 AAPotentialConstantValuesImpl,
9827 PotentialConstantIntValuesState> {
9828 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9829 AAPotentialConstantValuesImpl,
9831 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9832 : Base(IRP, A) {}
9833
9834 /// See AbstractAttribute::trackStatistics()
9835 void trackStatistics() const override {
9836 STATS_DECLTRACK_ARG_ATTR(potential_values)
9837 }
9838};
9839
9840struct AAPotentialConstantValuesReturned
9841 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9842 AAPotentialConstantValuesImpl> {
9843 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9844 AAPotentialConstantValuesImpl>;
9845 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9846 : Base(IRP, A) {}
9847
9848 void initialize(Attributor &A) override {
9849 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9850 indicatePessimisticFixpoint();
9851 Base::initialize(A);
9852 }
9853
9854 /// See AbstractAttribute::trackStatistics()
9855 void trackStatistics() const override {
9856 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9857 }
9858};
9859
9860struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9861 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9862 : AAPotentialConstantValuesImpl(IRP, A) {}
9863
9864 /// See AbstractAttribute::initialize(..).
9865 void initialize(Attributor &A) override {
9866 AAPotentialConstantValuesImpl::initialize(A);
9867 if (isAtFixpoint())
9868 return;
9869
9870 Value &V = getAssociatedValue();
9871
9872 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9873 unionAssumed(C->getValue());
9874 indicateOptimisticFixpoint();
9875 return;
9876 }
9877
9878 if (isa<UndefValue>(&V)) {
9879 unionAssumedWithUndef();
9880 indicateOptimisticFixpoint();
9881 return;
9882 }
9883
9884 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9885 return;
9886
9887 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9888 return;
9889
9890 indicatePessimisticFixpoint();
9891
9892 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9893 << getAssociatedValue() << "\n");
9894 }
9895
9896 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9897 const APInt &RHS) {
9898 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9899 }
9900
9901 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9902 uint32_t ResultBitWidth) {
9903 Instruction::CastOps CastOp = CI->getOpcode();
9904 switch (CastOp) {
9905 default:
9906 llvm_unreachable("unsupported or not integer cast");
9907 case Instruction::Trunc:
9908 return Src.trunc(ResultBitWidth);
9909 case Instruction::SExt:
9910 return Src.sext(ResultBitWidth);
9911 case Instruction::ZExt:
9912 return Src.zext(ResultBitWidth);
9913 case Instruction::BitCast:
9914 return Src;
9915 }
9916 }
9917
9918 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9919 const APInt &LHS, const APInt &RHS,
9920 bool &SkipOperation, bool &Unsupported) {
9921 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9922 // Unsupported is set to true when the binary operator is not supported.
9923 // SkipOperation is set to true when UB occur with the given operand pair
9924 // (LHS, RHS).
9925 // TODO: we should look at nsw and nuw keywords to handle operations
9926 // that create poison or undef value.
9927 switch (BinOpcode) {
9928 default:
9929 Unsupported = true;
9930 return LHS;
9931 case Instruction::Add:
9932 return LHS + RHS;
9933 case Instruction::Sub:
9934 return LHS - RHS;
9935 case Instruction::Mul:
9936 return LHS * RHS;
9937 case Instruction::UDiv:
9938 if (RHS.isZero()) {
9939 SkipOperation = true;
9940 return LHS;
9941 }
9942 return LHS.udiv(RHS);
9943 case Instruction::SDiv:
9944 if (RHS.isZero()) {
9945 SkipOperation = true;
9946 return LHS;
9947 }
9948 return LHS.sdiv(RHS);
9949 case Instruction::URem:
9950 if (RHS.isZero()) {
9951 SkipOperation = true;
9952 return LHS;
9953 }
9954 return LHS.urem(RHS);
9955 case Instruction::SRem:
9956 if (RHS.isZero()) {
9957 SkipOperation = true;
9958 return LHS;
9959 }
9960 return LHS.srem(RHS);
9961 case Instruction::Shl:
9962 return LHS.shl(RHS);
9963 case Instruction::LShr:
9964 return LHS.lshr(RHS);
9965 case Instruction::AShr:
9966 return LHS.ashr(RHS);
9967 case Instruction::And:
9968 return LHS & RHS;
9969 case Instruction::Or:
9970 return LHS | RHS;
9971 case Instruction::Xor:
9972 return LHS ^ RHS;
9973 }
9974 }
9975
9976 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
9977 const APInt &LHS, const APInt &RHS) {
9978 bool SkipOperation = false;
9979 bool Unsupported = false;
9980 APInt Result =
9981 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
9982 if (Unsupported)
9983 return false;
9984 // If SkipOperation is true, we can ignore this operand pair (L, R).
9985 if (!SkipOperation)
9986 unionAssumed(Result);
9987 return isValidState();
9988 }
9989
9990 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
9991 auto AssumedBefore = getAssumed();
9992 Value *LHS = ICI->getOperand(0);
9993 Value *RHS = ICI->getOperand(1);
9994
9995 bool LHSContainsUndef = false, RHSContainsUndef = false;
9996 SetTy LHSAAPVS, RHSAAPVS;
9997 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
9998 LHSContainsUndef, /* ForSelf */ false) ||
9999 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10000 RHSContainsUndef, /* ForSelf */ false))
10001 return indicatePessimisticFixpoint();
10002
10003 // TODO: make use of undef flag to limit potential values aggressively.
10004 bool MaybeTrue = false, MaybeFalse = false;
10005 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
10006 if (LHSContainsUndef && RHSContainsUndef) {
10007 // The result of any comparison between undefs can be soundly replaced
10008 // with undef.
10009 unionAssumedWithUndef();
10010 } else if (LHSContainsUndef) {
10011 for (const APInt &R : RHSAAPVS) {
10012 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10013 MaybeTrue |= CmpResult;
10014 MaybeFalse |= !CmpResult;
10015 if (MaybeTrue & MaybeFalse)
10016 return indicatePessimisticFixpoint();
10017 }
10018 } else if (RHSContainsUndef) {
10019 for (const APInt &L : LHSAAPVS) {
10020 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10021 MaybeTrue |= CmpResult;
10022 MaybeFalse |= !CmpResult;
10023 if (MaybeTrue & MaybeFalse)
10024 return indicatePessimisticFixpoint();
10025 }
10026 } else {
10027 for (const APInt &L : LHSAAPVS) {
10028 for (const APInt &R : RHSAAPVS) {
10029 bool CmpResult = calculateICmpInst(ICI, L, R);
10030 MaybeTrue |= CmpResult;
10031 MaybeFalse |= !CmpResult;
10032 if (MaybeTrue & MaybeFalse)
10033 return indicatePessimisticFixpoint();
10034 }
10035 }
10036 }
10037 if (MaybeTrue)
10038 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
10039 if (MaybeFalse)
10040 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
10041 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10042 : ChangeStatus::CHANGED;
10043 }
10044
10045 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
10046 auto AssumedBefore = getAssumed();
10047 Value *LHS = SI->getTrueValue();
10048 Value *RHS = SI->getFalseValue();
10049
10050 bool UsedAssumedInformation = false;
10051 std::optional<Constant *> C = A.getAssumedConstant(
10052 *SI->getCondition(), *this, UsedAssumedInformation);
10053
10054 // Check if we only need one operand.
10055 bool OnlyLeft = false, OnlyRight = false;
10056 if (C && *C && (*C)->isOneValue())
10057 OnlyLeft = true;
10058 else if (C && *C && (*C)->isZeroValue())
10059 OnlyRight = true;
10060
10061 bool LHSContainsUndef = false, RHSContainsUndef = false;
10062 SetTy LHSAAPVS, RHSAAPVS;
10063 if (!OnlyRight &&
10064 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
10065 LHSContainsUndef, /* ForSelf */ false))
10066 return indicatePessimisticFixpoint();
10067
10068 if (!OnlyLeft &&
10069 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10070 RHSContainsUndef, /* ForSelf */ false))
10071 return indicatePessimisticFixpoint();
10072
10073 if (OnlyLeft || OnlyRight) {
10074 // select (true/false), lhs, rhs
10075 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10076 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10077
10078 if (Undef)
10079 unionAssumedWithUndef();
10080 else {
10081 for (const auto &It : *OpAA)
10082 unionAssumed(It);
10083 }
10084
10085 } else if (LHSContainsUndef && RHSContainsUndef) {
10086 // select i1 *, undef , undef => undef
10087 unionAssumedWithUndef();
10088 } else {
10089 for (const auto &It : LHSAAPVS)
10090 unionAssumed(It);
10091 for (const auto &It : RHSAAPVS)
10092 unionAssumed(It);
10093 }
10094 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10095 : ChangeStatus::CHANGED;
10096 }
10097
10098 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
10099 auto AssumedBefore = getAssumed();
10100 if (!CI->isIntegerCast())
10101 return indicatePessimisticFixpoint();
10102 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
10103 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
10104 Value *Src = CI->getOperand(0);
10105
10106 bool SrcContainsUndef = false;
10107 SetTy SrcPVS;
10108 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
10109 SrcContainsUndef, /* ForSelf */ false))
10110 return indicatePessimisticFixpoint();
10111
10112 if (SrcContainsUndef)
10113 unionAssumedWithUndef();
10114 else {
10115 for (const APInt &S : SrcPVS) {
10116 APInt T = calculateCastInst(CI, S, ResultBitWidth);
10117 unionAssumed(T);
10118 }
10119 }
10120 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10121 : ChangeStatus::CHANGED;
10122 }
10123
10124 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
10125 auto AssumedBefore = getAssumed();
10126 Value *LHS = BinOp->getOperand(0);
10127 Value *RHS = BinOp->getOperand(1);
10128
10129 bool LHSContainsUndef = false, RHSContainsUndef = false;
10130 SetTy LHSAAPVS, RHSAAPVS;
10131 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
10132 LHSContainsUndef, /* ForSelf */ false) ||
10133 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10134 RHSContainsUndef, /* ForSelf */ false))
10135 return indicatePessimisticFixpoint();
10136
10137 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
10138
10139 // TODO: make use of undef flag to limit potential values aggressively.
10140 if (LHSContainsUndef && RHSContainsUndef) {
10141 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10142 return indicatePessimisticFixpoint();
10143 } else if (LHSContainsUndef) {
10144 for (const APInt &R : RHSAAPVS) {
10145 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10146 return indicatePessimisticFixpoint();
10147 }
10148 } else if (RHSContainsUndef) {
10149 for (const APInt &L : LHSAAPVS) {
10150 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10151 return indicatePessimisticFixpoint();
10152 }
10153 } else {
10154 for (const APInt &L : LHSAAPVS) {
10155 for (const APInt &R : RHSAAPVS) {
10156 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10157 return indicatePessimisticFixpoint();
10158 }
10159 }
10160 }
10161 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10162 : ChangeStatus::CHANGED;
10163 }
10164
10165 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10166 auto AssumedBefore = getAssumed();
10167 SetTy Incoming;
10168 bool ContainsUndef;
10169 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
10170 ContainsUndef, /* ForSelf */ true))
10171 return indicatePessimisticFixpoint();
10172 if (ContainsUndef) {
10173 unionAssumedWithUndef();
10174 } else {
10175 for (const auto &It : Incoming)
10176 unionAssumed(It);
10177 }
10178 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10179 : ChangeStatus::CHANGED;
10180 }
10181
10182 /// See AbstractAttribute::updateImpl(...).
10183 ChangeStatus updateImpl(Attributor &A) override {
10184 Value &V = getAssociatedValue();
10186
10187 if (auto *ICI = dyn_cast<ICmpInst>(I))
10188 return updateWithICmpInst(A, ICI);
10189
10190 if (auto *SI = dyn_cast<SelectInst>(I))
10191 return updateWithSelectInst(A, SI);
10192
10193 if (auto *CI = dyn_cast<CastInst>(I))
10194 return updateWithCastInst(A, CI);
10195
10196 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
10197 return updateWithBinaryOperator(A, BinOp);
10198
10199 if (isa<PHINode>(I) || isa<LoadInst>(I))
10200 return updateWithInstruction(A, I);
10201
10202 return indicatePessimisticFixpoint();
10203 }
10204
10205 /// See AbstractAttribute::trackStatistics()
10206 void trackStatistics() const override {
10207 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10208 }
10209};
10210
10211struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10212 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10213 : AAPotentialConstantValuesImpl(IRP, A) {}
10214
10215 /// See AbstractAttribute::initialize(...).
10216 ChangeStatus updateImpl(Attributor &A) override {
10218 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10219 "not be called");
10220 }
10221
10222 /// See AbstractAttribute::trackStatistics()
10223 void trackStatistics() const override {
10224 STATS_DECLTRACK_FN_ATTR(potential_values)
10225 }
10226};
10227
10228struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10229 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10230 : AAPotentialConstantValuesFunction(IRP, A) {}
10231
10232 /// See AbstractAttribute::trackStatistics()
10233 void trackStatistics() const override {
10234 STATS_DECLTRACK_CS_ATTR(potential_values)
10235 }
10236};
10237
10238struct AAPotentialConstantValuesCallSiteReturned
10239 : AACalleeToCallSite<AAPotentialConstantValues,
10240 AAPotentialConstantValuesImpl> {
10241 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10242 Attributor &A)
10243 : AACalleeToCallSite<AAPotentialConstantValues,
10244 AAPotentialConstantValuesImpl>(IRP, A) {}
10245
10246 /// See AbstractAttribute::trackStatistics()
10247 void trackStatistics() const override {
10248 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10249 }
10250};
10251
10252struct AAPotentialConstantValuesCallSiteArgument
10253 : AAPotentialConstantValuesFloating {
10254 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10255 Attributor &A)
10256 : AAPotentialConstantValuesFloating(IRP, A) {}
10257
10258 /// See AbstractAttribute::initialize(..).
10259 void initialize(Attributor &A) override {
10260 AAPotentialConstantValuesImpl::initialize(A);
10261 if (isAtFixpoint())
10262 return;
10263
10264 Value &V = getAssociatedValue();
10265
10266 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10267 unionAssumed(C->getValue());
10268 indicateOptimisticFixpoint();
10269 return;
10270 }
10271
10272 if (isa<UndefValue>(&V)) {
10273 unionAssumedWithUndef();
10274 indicateOptimisticFixpoint();
10275 return;
10276 }
10277 }
10278
10279 /// See AbstractAttribute::updateImpl(...).
10280 ChangeStatus updateImpl(Attributor &A) override {
10281 Value &V = getAssociatedValue();
10282 auto AssumedBefore = getAssumed();
10283 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10284 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10285 if (!AA)
10286 return indicatePessimisticFixpoint();
10287 const auto &S = AA->getAssumed();
10288 unionAssumed(S);
10289 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10290 : ChangeStatus::CHANGED;
10291 }
10292
10293 /// See AbstractAttribute::trackStatistics()
10294 void trackStatistics() const override {
10295 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10296 }
10297};
10298} // namespace
10299
10300/// ------------------------ NoUndef Attribute ---------------------------------
10302 Attribute::AttrKind ImpliedAttributeKind,
10303 bool IgnoreSubsumingPositions) {
10304 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10305 "Unexpected attribute kind");
10306 if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10307 Attribute::NoUndef))
10308 return true;
10309
10310 Value &Val = IRP.getAssociatedValue();
10313 LLVMContext &Ctx = Val.getContext();
10314 A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
10315 return true;
10316 }
10317
10318 return false;
10319}
10320
10321namespace {
10322struct AANoUndefImpl : AANoUndef {
10323 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10324
10325 /// See AbstractAttribute::initialize(...).
10326 void initialize(Attributor &A) override {
10327 Value &V = getAssociatedValue();
10328 if (isa<UndefValue>(V))
10329 indicatePessimisticFixpoint();
10330 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10331 }
10332
10333 /// See followUsesInMBEC
10334 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10335 AANoUndef::StateType &State) {
10336 const Value *UseV = U->get();
10337 const DominatorTree *DT = nullptr;
10338 AssumptionCache *AC = nullptr;
10339 InformationCache &InfoCache = A.getInfoCache();
10340 if (Function *F = getAnchorScope()) {
10341 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10342 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10343 }
10344 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10345 bool TrackUse = false;
10346 // Track use for instructions which must produce undef or poison bits when
10347 // at least one operand contains such bits.
10349 TrackUse = true;
10350 return TrackUse;
10351 }
10352
10353 /// See AbstractAttribute::getAsStr().
10354 const std::string getAsStr(Attributor *A) const override {
10355 return getAssumed() ? "noundef" : "may-undef-or-poison";
10356 }
10357
10358 ChangeStatus manifest(Attributor &A) override {
10359 // We don't manifest noundef attribute for dead positions because the
10360 // associated values with dead positions would be replaced with undef
10361 // values.
10362 bool UsedAssumedInformation = false;
10363 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10364 UsedAssumedInformation))
10365 return ChangeStatus::UNCHANGED;
10366 // A position whose simplified value does not have any value is
10367 // considered to be dead. We don't manifest noundef in such positions for
10368 // the same reason above.
10369 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10371 .has_value())
10372 return ChangeStatus::UNCHANGED;
10373 return AANoUndef::manifest(A);
10374 }
10375};
10376
10377struct AANoUndefFloating : public AANoUndefImpl {
10378 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10379 : AANoUndefImpl(IRP, A) {}
10380
10381 /// See AbstractAttribute::initialize(...).
10382 void initialize(Attributor &A) override {
10383 AANoUndefImpl::initialize(A);
10384 if (!getState().isAtFixpoint() && getAnchorScope() &&
10385 !getAnchorScope()->isDeclaration())
10386 if (Instruction *CtxI = getCtxI())
10387 followUsesInMBEC(*this, A, getState(), *CtxI);
10388 }
10389
10390 /// See AbstractAttribute::updateImpl(...).
10391 ChangeStatus updateImpl(Attributor &A) override {
10392 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10393 bool IsKnownNoUndef;
10395 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10396 };
10397
10398 bool Stripped;
10399 bool UsedAssumedInformation = false;
10400 Value *AssociatedValue = &getAssociatedValue();
10402 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10403 AA::AnyScope, UsedAssumedInformation))
10404 Stripped = false;
10405 else
10406 Stripped =
10407 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10408
10409 if (!Stripped) {
10410 // If we haven't stripped anything we might still be able to use a
10411 // different AA, but only if the IRP changes. Effectively when we
10412 // interpret this not as a call site value but as a floating/argument
10413 // value.
10414 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
10415 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10416 return indicatePessimisticFixpoint();
10417 return ChangeStatus::UNCHANGED;
10418 }
10419
10420 for (const auto &VAC : Values)
10421 if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
10422 return indicatePessimisticFixpoint();
10423
10424 return ChangeStatus::UNCHANGED;
10425 }
10426
10427 /// See AbstractAttribute::trackStatistics()
10428 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10429};
10430
10431struct AANoUndefReturned final
10432 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10433 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10434 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10435
10436 /// See AbstractAttribute::trackStatistics()
10437 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10438};
10439
10440struct AANoUndefArgument final
10441 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10442 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10443 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10444
10445 /// See AbstractAttribute::trackStatistics()
10446 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10447};
10448
10449struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10450 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10451 : AANoUndefFloating(IRP, A) {}
10452
10453 /// See AbstractAttribute::trackStatistics()
10454 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10455};
10456
10457struct AANoUndefCallSiteReturned final
10458 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10459 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10460 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10461
10462 /// See AbstractAttribute::trackStatistics()
10463 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10464};
10465
10466/// ------------------------ NoFPClass Attribute -------------------------------
10467
10468struct AANoFPClassImpl : AANoFPClass {
10469 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10470
10471 void initialize(Attributor &A) override {
10472 const IRPosition &IRP = getIRPosition();
10473
10474 Value &V = IRP.getAssociatedValue();
10475 if (isa<UndefValue>(V)) {
10476 indicateOptimisticFixpoint();
10477 return;
10478 }
10479
10481 A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
10482 for (const auto &Attr : Attrs) {
10483 addKnownBits(Attr.getNoFPClass());
10484 }
10485
10486 const DataLayout &DL = A.getDataLayout();
10487 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10488 KnownFPClass KnownFPClass = computeKnownFPClass(&V, DL);
10489 addKnownBits(~KnownFPClass.KnownFPClasses);
10490 }
10491
10492 if (Instruction *CtxI = getCtxI())
10493 followUsesInMBEC(*this, A, getState(), *CtxI);
10494 }
10495
10496 /// See followUsesInMBEC
10497 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10498 AANoFPClass::StateType &State) {
10499 // TODO: Determine what instructions can be looked through.
10500 auto *CB = dyn_cast<CallBase>(I);
10501 if (!CB)
10502 return false;
10503
10504 if (!CB->isArgOperand(U))
10505 return false;
10506
10507 unsigned ArgNo = CB->getArgOperandNo(U);
10508 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
10509 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))
10510 State.addKnownBits(NoFPAA->getState().getKnown());
10511 return false;
10512 }
10513
10514 const std::string getAsStr(Attributor *A) const override {
10515 std::string Result = "nofpclass";
10516 raw_string_ostream OS(Result);
10517 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10518 return Result;
10519 }
10520
10521 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10522 SmallVectorImpl<Attribute> &Attrs) const override {
10523 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10524 }
10525};
10526
10527struct AANoFPClassFloating : public AANoFPClassImpl {
10528 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10529 : AANoFPClassImpl(IRP, A) {}
10530
10531 /// See AbstractAttribute::updateImpl(...).
10532 ChangeStatus updateImpl(Attributor &A) override {
10534 bool UsedAssumedInformation = false;
10535 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10536 AA::AnyScope, UsedAssumedInformation)) {
10537 Values.push_back({getAssociatedValue(), getCtxI()});
10538 }
10539
10540 StateType T;
10541 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10542 const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10543 DepClassTy::REQUIRED);
10544 if (!AA || this == AA) {
10545 T.indicatePessimisticFixpoint();
10546 } else {
10547 const AANoFPClass::StateType &S =
10548 static_cast<const AANoFPClass::StateType &>(AA->getState());
10549 T ^= S;
10550 }
10551 return T.isValidState();
10552 };
10553
10554 for (const auto &VAC : Values)
10555 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10556 return indicatePessimisticFixpoint();
10557
10558 return clampStateAndIndicateChange(getState(), T);
10559 }
10560
10561 /// See AbstractAttribute::trackStatistics()
10562 void trackStatistics() const override {
10564 }
10565};
10566
10567struct AANoFPClassReturned final
10568 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10569 AANoFPClassImpl::StateType, false,
10570 Attribute::None, false> {
10571 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10572 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10573 AANoFPClassImpl::StateType, false,
10574 Attribute::None, false>(IRP, A) {}
10575
10576 /// See AbstractAttribute::trackStatistics()
10577 void trackStatistics() const override {
10579 }
10580};
10581
10582struct AANoFPClassArgument final
10583 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10584 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10585 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10586
10587 /// See AbstractAttribute::trackStatistics()
10588 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10589};
10590
10591struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10592 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10593 : AANoFPClassFloating(IRP, A) {}
10594
10595 /// See AbstractAttribute::trackStatistics()
10596 void trackStatistics() const override {
10598 }
10599};
10600
10601struct AANoFPClassCallSiteReturned final
10602 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10603 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10604 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10605
10606 /// See AbstractAttribute::trackStatistics()
10607 void trackStatistics() const override {
10609 }
10610};
10611
10612struct AACallEdgesImpl : public AACallEdges {
10613 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10614
10615 const SetVector<Function *> &getOptimisticEdges() const override {
10616 return CalledFunctions;
10617 }
10618
10619 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10620
10621 bool hasNonAsmUnknownCallee() const override {
10622 return HasUnknownCalleeNonAsm;
10623 }
10624
10625 const std::string getAsStr(Attributor *A) const override {
10626 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10627 std::to_string(CalledFunctions.size()) + "]";
10628 }
10629
10630 void trackStatistics() const override {}
10631
10632protected:
10633 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10634 if (CalledFunctions.insert(Fn)) {
10635 Change = ChangeStatus::CHANGED;
10636 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10637 << "\n");
10638 }
10639 }
10640
10641 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10642 if (!HasUnknownCallee)
10643 Change = ChangeStatus::CHANGED;
10644 if (NonAsm && !HasUnknownCalleeNonAsm)
10645 Change = ChangeStatus::CHANGED;
10646 HasUnknownCalleeNonAsm |= NonAsm;
10647 HasUnknownCallee = true;
10648 }
10649
10650private:
10651 /// Optimistic set of functions that might be called by this position.
10652 SetVector<Function *> CalledFunctions;
10653
10654 /// Is there any call with a unknown callee.
10655 bool HasUnknownCallee = false;
10656
10657 /// Is there any call with a unknown callee, excluding any inline asm.
10658 bool HasUnknownCalleeNonAsm = false;
10659};
10660
10661struct AACallEdgesCallSite : public AACallEdgesImpl {
10662 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10663 : AACallEdgesImpl(IRP, A) {}
10664 /// See AbstractAttribute::updateImpl(...).
10665 ChangeStatus updateImpl(Attributor &A) override {
10666 ChangeStatus Change = ChangeStatus::UNCHANGED;
10667
10668 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10669 if (Function *Fn = dyn_cast<Function>(&V)) {
10670 addCalledFunction(Fn, Change);
10671 } else {
10672 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10673 setHasUnknownCallee(true, Change);
10674 }
10675
10676 // Explore all values.
10677 return true;
10678 };
10679
10681 // Process any value that we might call.
10682 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10683 if (isa<Constant>(V)) {
10684 VisitValue(*V, CtxI);
10685 return;
10686 }
10687
10688 bool UsedAssumedInformation = false;
10689 Values.clear();
10690 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10691 AA::AnyScope, UsedAssumedInformation)) {
10692 Values.push_back({*V, CtxI});
10693 }
10694 for (auto &VAC : Values)
10695 VisitValue(*VAC.getValue(), VAC.getCtxI());
10696 };
10697
10698 CallBase *CB = cast<CallBase>(getCtxI());
10699
10700 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10701 if (IA->hasSideEffects() &&
10702 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10703 !hasAssumption(*CB, "ompx_no_call_asm")) {
10704 setHasUnknownCallee(false, Change);
10705 }
10706 return Change;
10707 }
10708
10709 if (CB->isIndirectCall())
10710 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10711 *this, getIRPosition(), DepClassTy::OPTIONAL))
10712 if (IndirectCallAA->foreachCallee(
10713 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10714 return Change;
10715
10716 // The most simple case.
10717 ProcessCalledOperand(CB->getCalledOperand(), CB);
10718
10719 // Process callback functions.
10720 SmallVector<const Use *, 4u> CallbackUses;
10721 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10722 for (const Use *U : CallbackUses)
10723 ProcessCalledOperand(U->get(), CB);
10724
10725 return Change;
10726 }
10727};
10728
10729struct AACallEdgesFunction : public AACallEdgesImpl {
10730 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10731 : AACallEdgesImpl(IRP, A) {}
10732
10733 /// See AbstractAttribute::updateImpl(...).
10734 ChangeStatus updateImpl(Attributor &A) override {
10735 ChangeStatus Change = ChangeStatus::UNCHANGED;
10736
10737 auto ProcessCallInst = [&](Instruction &Inst) {
10738 CallBase &CB = cast<CallBase>(Inst);
10739
10740 auto *CBEdges = A.getAAFor<AACallEdges>(
10741 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10742 if (!CBEdges)
10743 return false;
10744 if (CBEdges->hasNonAsmUnknownCallee())
10745 setHasUnknownCallee(true, Change);
10746 if (CBEdges->hasUnknownCallee())
10747 setHasUnknownCallee(false, Change);
10748
10749 for (Function *F : CBEdges->getOptimisticEdges())
10750 addCalledFunction(F, Change);
10751
10752 return true;
10753 };
10754
10755 // Visit all callable instructions.
10756 bool UsedAssumedInformation = false;
10757 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10758 UsedAssumedInformation,
10759 /* CheckBBLivenessOnly */ true)) {
10760 // If we haven't looked at all call like instructions, assume that there
10761 // are unknown callees.
10762 setHasUnknownCallee(true, Change);
10763 }
10764
10765 return Change;
10766 }
10767};
10768
10769/// -------------------AAInterFnReachability Attribute--------------------------
10770
10771struct AAInterFnReachabilityFunction
10772 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10773 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10774 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10775 : Base(IRP, A) {}
10776
10777 bool instructionCanReach(
10778 Attributor &A, const Instruction &From, const Function &To,
10779 const AA::InstExclusionSetTy *ExclusionSet) const override {
10780 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10781 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10782
10783 RQITy StackRQI(A, From, To, ExclusionSet, false);
10784 RQITy::Reachable Result;
10785 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10786 return NonConstThis->isReachableImpl(A, StackRQI,
10787 /*IsTemporaryRQI=*/true);
10788 return Result == RQITy::Reachable::Yes;
10789 }
10790
10791 bool isReachableImpl(Attributor &A, RQITy &RQI,
10792 bool IsTemporaryRQI) override {
10793 const Instruction *EntryI =
10794 &RQI.From->getFunction()->getEntryBlock().front();
10795 if (EntryI != RQI.From &&
10796 !instructionCanReach(A, *EntryI, *RQI.To, nullptr))
10797 return rememberResult(A, RQITy::Reachable::No, RQI, false,
10798 IsTemporaryRQI);
10799
10800 auto CheckReachableCallBase = [&](CallBase *CB) {
10801 auto *CBEdges = A.getAAFor<AACallEdges>(
10802 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10803 if (!CBEdges || !CBEdges->getState().isValidState())
10804 return false;
10805 // TODO Check To backwards in this case.
10806 if (CBEdges->hasUnknownCallee())
10807 return false;
10808
10809 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10810 if (Fn == RQI.To)
10811 return false;
10812
10813 if (Fn->isDeclaration()) {
10814 if (Fn->hasFnAttribute(Attribute::NoCallback))
10815 continue;
10816 // TODO Check To backwards in this case.
10817 return false;
10818 }
10819
10820 if (Fn == getAnchorScope()) {
10821 if (EntryI == RQI.From)
10822 continue;
10823 return false;
10824 }
10825
10826 const AAInterFnReachability *InterFnReachability =
10827 A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),
10828 DepClassTy::OPTIONAL);
10829
10830 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10831 if (!InterFnReachability ||
10832 InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10833 RQI.ExclusionSet))
10834 return false;
10835 }
10836 return true;
10837 };
10838
10839 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10840 *this, IRPosition::function(*RQI.From->getFunction()),
10841 DepClassTy::OPTIONAL);
10842
10843 // Determine call like instructions that we can reach from the inst.
10844 auto CheckCallBase = [&](Instruction &CBInst) {
10845 // There are usually less nodes in the call graph, check inter function
10846 // reachability first.
10847 if (CheckReachableCallBase(cast<CallBase>(&CBInst)))
10848 return true;
10849 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10850 A, *RQI.From, CBInst, RQI.ExclusionSet);
10851 };
10852
10853 bool UsedExclusionSet = /* conservative */ true;
10854 bool UsedAssumedInformation = false;
10855 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10856 UsedAssumedInformation,
10857 /* CheckBBLivenessOnly */ true))
10858 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10859 IsTemporaryRQI);
10860
10861 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10862 IsTemporaryRQI);
10863 }
10864
10865 void trackStatistics() const override {}
10866};
10867} // namespace
10868
10869template <typename AAType>
10870static std::optional<Constant *>
10872 const IRPosition &IRP, Type &Ty) {
10873 if (!Ty.isIntegerTy())
10874 return nullptr;
10875
10876 // This will also pass the call base context.
10877 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10878 if (!AA)
10879 return nullptr;
10880
10881 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10882
10883 if (!COpt.has_value()) {
10884 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10885 return std::nullopt;
10886 }
10887 if (auto *C = *COpt) {
10888 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10889 return C;
10890 }
10891 return nullptr;
10892}
10893
10895 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10897 Type &Ty = *IRP.getAssociatedType();
10898 std::optional<Value *> V;
10899 for (auto &It : Values) {
10900 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10901 if (V.has_value() && !*V)
10902 break;
10903 }
10904 if (!V.has_value())
10905 return UndefValue::get(&Ty);
10906 return *V;
10907}
10908
10909namespace {
10910struct AAPotentialValuesImpl : AAPotentialValues {
10911 using StateType = PotentialLLVMValuesState;
10912
10913 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10914 : AAPotentialValues(IRP, A) {}
10915
10916 /// See AbstractAttribute::initialize(..).
10917 void initialize(Attributor &A) override {
10918 if (A.hasSimplificationCallback(getIRPosition())) {
10919 indicatePessimisticFixpoint();
10920 return;
10921 }
10922 Value *Stripped = getAssociatedValue().stripPointerCasts();
10923 if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {
10924 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10925 getAnchorScope());
10926 indicateOptimisticFixpoint();
10927 return;
10928 }
10929 AAPotentialValues::initialize(A);
10930 }
10931
10932 /// See AbstractAttribute::getAsStr().
10933 const std::string getAsStr(Attributor *A) const override {
10934 std::string Str;
10935 llvm::raw_string_ostream OS(Str);
10936 OS << getState();
10937 return Str;
10938 }
10939
10940 template <typename AAType>
10941 static std::optional<Value *> askOtherAA(Attributor &A,
10942 const AbstractAttribute &AA,
10943 const IRPosition &IRP, Type &Ty) {
10945 return &IRP.getAssociatedValue();
10946 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
10947 if (!C)
10948 return std::nullopt;
10949 if (*C)
10950 if (auto *CC = AA::getWithType(**C, Ty))
10951 return CC;
10952 return nullptr;
10953 }
10954
10955 virtual void addValue(Attributor &A, StateType &State, Value &V,
10956 const Instruction *CtxI, AA::ValueScope S,
10957 Function *AnchorScope) const {
10958
10959 IRPosition ValIRP = IRPosition::value(V);
10960 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
10961 for (const auto &U : CB->args()) {
10962 if (U.get() != &V)
10963 continue;
10964 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
10965 break;
10966 }
10967 }
10968
10969 Value *VPtr = &V;
10970 if (ValIRP.getAssociatedType()->isIntegerTy()) {
10971 Type &Ty = *getAssociatedType();
10972 std::optional<Value *> SimpleV =
10973 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
10974 if (SimpleV.has_value() && !*SimpleV) {
10975 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
10976 *this, ValIRP, DepClassTy::OPTIONAL);
10977 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
10978 for (const auto &It : PotentialConstantsAA->getAssumedSet())
10979 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
10980 if (PotentialConstantsAA->undefIsContained())
10981 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
10982 return;
10983 }
10984 }
10985 if (!SimpleV.has_value())
10986 return;
10987
10988 if (*SimpleV)
10989 VPtr = *SimpleV;
10990 }
10991
10992 if (isa<ConstantInt>(VPtr))
10993 CtxI = nullptr;
10994 if (!AA::isValidInScope(*VPtr, AnchorScope))
10996
10997 State.unionAssumed({{*VPtr, CtxI}, S});
10998 }
10999
11000 /// Helper struct to tie a value+context pair together with the scope for
11001 /// which this is the simplified version.
11002 struct ItemInfo {
11003 AA::ValueAndContext I;
11005
11006 bool operator==(const ItemInfo &II) const {
11007 return II.I == I && II.S == S;
11008 };
11009 bool operator<(const ItemInfo &II) const {
11010 return std::tie(I, S) < std::tie(II.I, II.S);
11011 };
11012 };
11013
11014 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
11015 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11016 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
11017 if (!(CS & S))
11018 continue;
11019
11020 bool UsedAssumedInformation = false;
11022 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
11023 UsedAssumedInformation))
11024 return false;
11025
11026 for (auto &It : Values)
11027 ValueScopeMap[It] += CS;
11028 }
11029 for (auto &It : ValueScopeMap)
11030 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
11031 AA::ValueScope(It.second), getAnchorScope());
11032
11033 return true;
11034 }
11035
11036 void giveUpOnIntraprocedural(Attributor &A) {
11037 auto NewS = StateType::getBestState(getState());
11038 for (const auto &It : getAssumedSet()) {
11039 if (It.second == AA::Intraprocedural)
11040 continue;
11041 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
11042 AA::Interprocedural, getAnchorScope());
11043 }
11044 assert(!undefIsContained() && "Undef should be an explicit value!");
11045 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
11046 getAnchorScope());
11047 getState() = NewS;
11048 }
11049
11050 /// See AbstractState::indicatePessimisticFixpoint(...).
11051 ChangeStatus indicatePessimisticFixpoint() override {
11052 getState() = StateType::getBestState(getState());
11053 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
11054 AAPotentialValues::indicateOptimisticFixpoint();
11055 return ChangeStatus::CHANGED;
11056 }
11057
11058 /// See AbstractAttribute::updateImpl(...).
11059 ChangeStatus updateImpl(Attributor &A) override {
11060 return indicatePessimisticFixpoint();
11061 }
11062
11063 /// See AbstractAttribute::manifest(...).
11064 ChangeStatus manifest(Attributor &A) override {
11067 Values.clear();
11068 if (!getAssumedSimplifiedValues(A, Values, S))
11069 continue;
11070 Value &OldV = getAssociatedValue();
11071 if (isa<UndefValue>(OldV))
11072 continue;
11073 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
11074 if (!NewV || NewV == &OldV)
11075 continue;
11076 if (getCtxI() &&
11077 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
11078 continue;
11079 if (A.changeAfterManifest(getIRPosition(), *NewV))
11080 return ChangeStatus::CHANGED;
11081 }
11082 return ChangeStatus::UNCHANGED;
11083 }
11084
11085 bool getAssumedSimplifiedValues(
11086 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
11087 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
11088 if (!isValidState())
11089 return false;
11090 bool UsedAssumedInformation = false;
11091 for (const auto &It : getAssumedSet())
11092 if (It.second & S) {
11093 if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
11094 isa<SelectInst>(It.first.getValue()))) {
11095 if (A.getAssumedSimplifiedValues(
11096 IRPosition::inst(*cast<Instruction>(It.first.getValue())),
11097 this, Values, S, UsedAssumedInformation))
11098 continue;
11099 }
11100 Values.push_back(It.first);
11101 }
11102 assert(!undefIsContained() && "Undef should be an explicit value!");
11103 return true;
11104 }
11105};
11106
11107struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11108 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
11109 : AAPotentialValuesImpl(IRP, A) {}
11110
11111 /// See AbstractAttribute::updateImpl(...).
11112 ChangeStatus updateImpl(Attributor &A) override {
11113 auto AssumedBefore = getAssumed();
11114
11115 genericValueTraversal(A, &getAssociatedValue());
11116
11117 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11118 : ChangeStatus::CHANGED;
11119 }
11120
11121 /// Helper struct to remember which AAIsDead instances we actually used.
11122 struct LivenessInfo {
11123 const AAIsDead *LivenessAA = nullptr;
11124 bool AnyDead = false;
11125 };
11126
11127 /// Check if \p Cmp is a comparison we can simplify.
11128 ///
11129 /// We handle multiple cases, one in which at least one operand is an
11130 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
11131 /// operand. Return true if successful, in that case Worklist will be updated.
11132 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
11133 CmpInst::Predicate Pred, ItemInfo II,
11134 SmallVectorImpl<ItemInfo> &Worklist) {
11135
11136 // Simplify the operands first.
11137 bool UsedAssumedInformation = false;
11138 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
11139 auto GetSimplifiedValues = [&](Value &V,
11141 if (!A.getAssumedSimplifiedValues(
11142 IRPosition::value(V, getCallBaseContext()), this, Values,
11143 AA::Intraprocedural, UsedAssumedInformation)) {
11144 Values.clear();
11145 Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});
11146 }
11147 return Values.empty();
11148 };
11149 if (GetSimplifiedValues(*LHS, LHSValues))
11150 return true;
11151 if (GetSimplifiedValues(*RHS, RHSValues))
11152 return true;
11153
11154 LLVMContext &Ctx = LHS->getContext();
11155
11156 InformationCache &InfoCache = A.getInfoCache();
11157 Instruction *CmpI = dyn_cast<Instruction>(&Cmp);
11158 Function *F = CmpI ? CmpI->getFunction() : nullptr;
11159 const auto *DT =
11160 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)
11161 : nullptr;
11162 const auto *TLI =
11163 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
11164 auto *AC =
11165 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)
11166 : nullptr;
11167
11168 const DataLayout &DL = A.getDataLayout();
11169 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11170
11171 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11172 if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {
11173 addValue(A, getState(), *UndefValue::get(Cmp.getType()),
11174 /* CtxI */ nullptr, II.S, getAnchorScope());
11175 return true;
11176 }
11177
11178 // Handle the trivial case first in which we don't even need to think
11179 // about null or non-null.
11180 if (&LHSV == &RHSV &&
11182 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11184 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11185 getAnchorScope());
11186 return true;
11187 }
11188
11189 auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());
11190 auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());
11191 if (TypedLHS && TypedRHS) {
11192 Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);
11193 if (NewV && NewV != &Cmp) {
11194 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11195 getAnchorScope());
11196 return true;
11197 }
11198 }
11199
11200 // From now on we only handle equalities (==, !=).
11201 if (!CmpInst::isEquality(Pred))
11202 return false;
11203
11204 bool LHSIsNull = isa<ConstantPointerNull>(LHSV);
11205 bool RHSIsNull = isa<ConstantPointerNull>(RHSV);
11206 if (!LHSIsNull && !RHSIsNull)
11207 return false;
11208
11209 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11210 // non-nullptr operand and if we assume it's non-null we can conclude the
11211 // result of the comparison.
11212 assert((LHSIsNull || RHSIsNull) &&
11213 "Expected nullptr versus non-nullptr comparison at this point");
11214
11215 // The index is the operand that we assume is not null.
11216 unsigned PtrIdx = LHSIsNull;
11217 bool IsKnownNonNull;
11218 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11219 A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),
11220 DepClassTy::REQUIRED, IsKnownNonNull);
11221 if (!IsAssumedNonNull)
11222 return false;
11223
11224 // The new value depends on the predicate, true for != and false for ==.
11225 Constant *NewV =
11226 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11227 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11228 getAnchorScope());
11229 return true;
11230 };
11231
11232 for (auto &LHSValue : LHSValues)
11233 for (auto &RHSValue : RHSValues)
11234 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11235 return false;
11236 return true;
11237 }
11238
11239 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11240 SmallVectorImpl<ItemInfo> &Worklist) {
11241 const Instruction *CtxI = II.I.getCtxI();
11242 bool UsedAssumedInformation = false;
11243
11244 std::optional<Constant *> C =
11245 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11246 bool NoValueYet = !C.has_value();
11247 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11248 return true;
11249 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11250 if (CI->isZero())
11251 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11252 else
11253 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11254 } else if (&SI == &getAssociatedValue()) {
11255 // We could not simplify the condition, assume both values.
11256 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11257 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11258 } else {
11259 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11260 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11261 if (!SimpleV.has_value())
11262 return true;
11263 if (*SimpleV) {
11264 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11265 return true;
11266 }
11267 return false;
11268 }
11269 return true;
11270 }
11271
11272 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11273 SmallVectorImpl<ItemInfo> &Worklist) {
11274 SmallSetVector<Value *, 4> PotentialCopies;
11275 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11276 bool UsedAssumedInformation = false;
11277 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11278 PotentialValueOrigins, *this,
11279 UsedAssumedInformation,
11280 /* OnlyExact */ true)) {
11281 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11282 "loaded values for load instruction "
11283 << LI << "\n");
11284 return false;
11285 }
11286
11287 // Do not simplify loads that are only used in llvm.assume if we cannot also
11288 // remove all stores that may feed into the load. The reason is that the
11289 // assume is probably worth something as long as the stores are around.
11290 InformationCache &InfoCache = A.getInfoCache();
11291 if (InfoCache.isOnlyUsedByAssume(LI)) {
11292 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11293 if (!I || isa<AssumeInst>(I))
11294 return true;
11295 if (auto *SI = dyn_cast<StoreInst>(I))
11296 return A.isAssumedDead(SI->getOperandUse(0), this,
11297 /* LivenessAA */ nullptr,
11298 UsedAssumedInformation,
11299 /* CheckBBLivenessOnly */ false);
11300 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11301 UsedAssumedInformation,
11302 /* CheckBBLivenessOnly */ false);
11303 })) {
11304 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11305 "and we cannot delete all the stores: "
11306 << LI << "\n");
11307 return false;
11308 }
11309 }
11310
11311 // Values have to be dynamically unique or we loose the fact that a
11312 // single llvm::Value might represent two runtime values (e.g.,
11313 // stack locations in different recursive calls).
11314 const Instruction *CtxI = II.I.getCtxI();
11315 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11316 bool AllLocal = ScopeIsLocal;
11317 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11318 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11319 return AA::isDynamicallyUnique(A, *this, *PC);
11320 });
11321 if (!DynamicallyUnique) {
11322 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11323 "values are dynamically unique: "
11324 << LI << "\n");
11325 return false;
11326 }
11327
11328 for (auto *PotentialCopy : PotentialCopies) {
11329 if (AllLocal) {
11330 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11331 } else {
11332 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11333 }
11334 }
11335 if (!AllLocal && ScopeIsLocal)
11336 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11337 return true;
11338 }
11339
11340 bool handlePHINode(
11341 Attributor &A, PHINode &PHI, ItemInfo II,
11342 SmallVectorImpl<ItemInfo> &Worklist,
11343 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11344 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11345 LivenessInfo &LI = LivenessAAs[&F];
11346 if (!LI.LivenessAA)
11347 LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11348 DepClassTy::NONE);
11349 return LI;
11350 };
11351
11352 if (&PHI == &getAssociatedValue()) {
11353 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11354 const auto *CI =
11355 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11356 *PHI.getFunction());
11357
11358 Cycle *C = nullptr;
11359 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11360 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11361 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11362 if (LI.LivenessAA &&
11363 LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11364 LI.AnyDead = true;
11365 continue;
11366 }
11367 Value *V = PHI.getIncomingValue(u);
11368 if (V == &PHI)
11369 continue;
11370
11371 // If the incoming value is not the PHI but an instruction in the same
11372 // cycle we might have multiple versions of it flying around.
11373 if (CyclePHI && isa<Instruction>(V) &&
11374 (!C || C->contains(cast<Instruction>(V)->getParent())))
11375 return false;
11376
11377 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11378 }
11379 return true;
11380 }
11381
11382 bool UsedAssumedInformation = false;
11383 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11384 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11385 if (!SimpleV.has_value())
11386 return true;
11387 if (!(*SimpleV))
11388 return false;
11389 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11390 return true;
11391 }
11392
11393 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11394 /// simplify any operand of the instruction \p I. Return true if successful,
11395 /// in that case Worklist will be updated.
11396 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11397 SmallVectorImpl<ItemInfo> &Worklist) {
11398 bool SomeSimplified = false;
11399 bool UsedAssumedInformation = false;
11400
11401 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11402 int Idx = 0;
11403 for (Value *Op : I.operands()) {
11404 const auto &SimplifiedOp = A.getAssumedSimplified(
11405 IRPosition::value(*Op, getCallBaseContext()), *this,
11406 UsedAssumedInformation, AA::Intraprocedural);
11407 // If we are not sure about any operand we are not sure about the entire
11408 // instruction, we'll wait.
11409 if (!SimplifiedOp.has_value())
11410 return true;
11411
11412 if (*SimplifiedOp)
11413 NewOps[Idx] = *SimplifiedOp;
11414 else
11415 NewOps[Idx] = Op;
11416
11417 SomeSimplified |= (NewOps[Idx] != Op);
11418 ++Idx;
11419 }
11420
11421 // We won't bother with the InstSimplify interface if we didn't simplify any
11422 // operand ourselves.
11423 if (!SomeSimplified)
11424 return false;
11425
11426 InformationCache &InfoCache = A.getInfoCache();
11427 Function *F = I.getFunction();
11428 const auto *DT =
11429 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11430 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11431 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11432
11433 const DataLayout &DL = I.getDataLayout();
11434 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11435 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11436 if (!NewV || NewV == &I)
11437 return false;
11438
11439 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11440 << *NewV << "\n");
11441 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11442 return true;
11443 }
11444
11446 Attributor &A, Instruction &I, ItemInfo II,
11447 SmallVectorImpl<ItemInfo> &Worklist,
11448 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11449 if (auto *CI = dyn_cast<CmpInst>(&I))
11450 return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11451 CI->getPredicate(), II, Worklist);
11452
11453 switch (I.getOpcode()) {
11454 case Instruction::Select:
11455 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11456 case Instruction::PHI:
11457 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11458 case Instruction::Load:
11459 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11460 default:
11461 return handleGenericInst(A, I, II, Worklist);
11462 };
11463 return false;
11464 }
11465
11466 void genericValueTraversal(Attributor &A, Value *InitialV) {
11467 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11468
11469 SmallSet<ItemInfo, 16> Visited;
11471 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11472
11473 int Iteration = 0;
11474 do {
11475 ItemInfo II = Worklist.pop_back_val();
11476 Value *V = II.I.getValue();
11477 assert(V);
11478 const Instruction *CtxI = II.I.getCtxI();
11479 AA::ValueScope S = II.S;
11480
11481 // Check if we should process the current value. To prevent endless
11482 // recursion keep a record of the values we followed!
11483 if (!Visited.insert(II).second)
11484 continue;
11485
11486 // Make sure we limit the compile time for complex expressions.
11487 if (Iteration++ >= MaxPotentialValuesIterations) {
11488 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11489 << Iteration << "!\n");
11490 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11491 continue;
11492 }
11493
11494 // Explicitly look through calls with a "returned" attribute if we do
11495 // not have a pointer as stripPointerCasts only works on them.
11496 Value *NewV = nullptr;
11497 if (V->getType()->isPointerTy()) {
11498 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11499 } else {
11500 if (auto *CB = dyn_cast<CallBase>(V))
11501 if (auto *Callee =
11503 for (Argument &Arg : Callee->args())
11504 if (Arg.hasReturnedAttr()) {
11505 NewV = CB->getArgOperand(Arg.getArgNo());
11506 break;
11507 }
11508 }
11509 }
11510 if (NewV && NewV != V) {
11511 Worklist.push_back({{*NewV, CtxI}, S});
11512 continue;
11513 }
11514
11515 if (auto *I = dyn_cast<Instruction>(V)) {
11516 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11517 continue;
11518 }
11519
11520 if (V != InitialV || isa<Argument>(V))
11521 if (recurseForValue(A, IRPosition::value(*V), II.S))
11522 continue;
11523
11524 // If we haven't stripped anything we give up.
11525 if (V == InitialV && CtxI == getCtxI()) {
11526 indicatePessimisticFixpoint();
11527 return;
11528 }
11529
11530 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11531 } while (!Worklist.empty());
11532
11533 // If we actually used liveness information so we have to record a
11534 // dependence.
11535 for (auto &It : LivenessAAs)
11536 if (It.second.AnyDead)
11537 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11538 }
11539
11540 /// See AbstractAttribute::trackStatistics()
11541 void trackStatistics() const override {
11542 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11543 }
11544};
11545
11546struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11547 using Base = AAPotentialValuesImpl;
11548 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11549 : Base(IRP, A) {}
11550
11551 /// See AbstractAttribute::initialize(..).
11552 void initialize(Attributor &A) override {
11553 auto &Arg = cast<Argument>(getAssociatedValue());
11555 indicatePessimisticFixpoint();
11556 }
11557
11558 /// See AbstractAttribute::updateImpl(...).
11559 ChangeStatus updateImpl(Attributor &A) override {
11560 auto AssumedBefore = getAssumed();
11561
11562 unsigned ArgNo = getCalleeArgNo();
11563
11564 bool UsedAssumedInformation = false;
11566 auto CallSitePred = [&](AbstractCallSite ACS) {
11567 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11568 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11569 return false;
11570
11571 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11573 UsedAssumedInformation))
11574 return false;
11575
11576 return isValidState();
11577 };
11578
11579 if (!A.checkForAllCallSites(CallSitePred, *this,
11580 /* RequireAllCallSites */ true,
11581 UsedAssumedInformation))
11582 return indicatePessimisticFixpoint();
11583
11584 Function *Fn = getAssociatedFunction();
11585 bool AnyNonLocal = false;
11586 for (auto &It : Values) {
11587 if (isa<Constant>(It.getValue())) {
11588 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11589 getAnchorScope());
11590 continue;
11591 }
11592 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11593 return indicatePessimisticFixpoint();
11594
11595 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11596 if (Arg->getParent() == Fn) {
11597 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11598 getAnchorScope());
11599 continue;
11600 }
11601 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11602 getAnchorScope());
11603 AnyNonLocal = true;
11604 }
11605 assert(!undefIsContained() && "Undef should be an explicit value!");
11606 if (AnyNonLocal)
11607 giveUpOnIntraprocedural(A);
11608
11609 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11610 : ChangeStatus::CHANGED;
11611 }
11612
11613 /// See AbstractAttribute::trackStatistics()
11614 void trackStatistics() const override {
11615 STATS_DECLTRACK_ARG_ATTR(potential_values)
11616 }
11617};
11618
11619struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11620 using Base = AAPotentialValuesFloating;
11621 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11622 : Base(IRP, A) {}
11623
11624 /// See AbstractAttribute::initialize(..).
11625 void initialize(Attributor &A) override {
11626 Function *F = getAssociatedFunction();
11627 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11628 indicatePessimisticFixpoint();
11629 return;
11630 }
11631
11632 for (Argument &Arg : F->args())
11633 if (Arg.hasReturnedAttr()) {
11634 addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
11635 ReturnedArg = &Arg;
11636 break;
11637 }
11638 if (!A.isFunctionIPOAmendable(*F) ||
11639 A.hasSimplificationCallback(getIRPosition())) {
11640 if (!ReturnedArg)
11641 indicatePessimisticFixpoint();
11642 else
11643 indicateOptimisticFixpoint();
11644 }
11645 }
11646
11647 /// See AbstractAttribute::updateImpl(...).
11648 ChangeStatus updateImpl(Attributor &A) override {
11649 auto AssumedBefore = getAssumed();
11650 bool UsedAssumedInformation = false;
11651
11653 Function *AnchorScope = getAnchorScope();
11654 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11655 bool AddValues) {
11657 Values.clear();
11658 if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
11659 UsedAssumedInformation,
11660 /* RecurseForSelectAndPHI */ true))
11661 return false;
11662 if (!AddValues)
11663 continue;
11664
11665 bool AllInterAreIntra = false;
11666 if (S == AA::Interprocedural)
11667 AllInterAreIntra =
11668 llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
11669 return AA::isValidInScope(*VAC.getValue(), AnchorScope);
11670 });
11671
11672 for (const AA::ValueAndContext &VAC : Values) {
11673 addValue(A, getState(), *VAC.getValue(),
11674 VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11675 AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11676 }
11677 if (AllInterAreIntra)
11678 break;
11679 }
11680 return true;
11681 };
11682
11683 if (ReturnedArg) {
11684 HandleReturnedValue(*ReturnedArg, nullptr, true);
11685 } else {
11686 auto RetInstPred = [&](Instruction &RetI) {
11687 bool AddValues = true;
11688 if (isa<PHINode>(RetI.getOperand(0)) ||
11689 isa<SelectInst>(RetI.getOperand(0))) {
11690 addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
11691 AnchorScope);
11692 AddValues = false;
11693 }
11694 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11695 };
11696
11697 if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11698 UsedAssumedInformation,
11699 /* CheckBBLivenessOnly */ true))
11700 return indicatePessimisticFixpoint();
11701 }
11702
11703 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11704 : ChangeStatus::CHANGED;
11705 }
11706
11707 ChangeStatus manifest(Attributor &A) override {
11708 if (ReturnedArg)
11709 return ChangeStatus::UNCHANGED;
11711 if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
11712 /* RecurseForSelectAndPHI */ true))
11713 return ChangeStatus::UNCHANGED;
11714 Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
11715 if (!NewVal)
11716 return ChangeStatus::UNCHANGED;
11717
11718 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11719 if (auto *Arg = dyn_cast<Argument>(NewVal)) {
11720 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11721 "Number of function with unique return");
11722 Changed |= A.manifestAttrs(
11724 {Attribute::get(Arg->getContext(), Attribute::Returned)});
11725 STATS_DECLTRACK_ARG_ATTR(returned);
11726 }
11727
11728 auto RetInstPred = [&](Instruction &RetI) {
11729 Value *RetOp = RetI.getOperand(0);
11730 if (isa<UndefValue>(RetOp) || RetOp == NewVal)
11731 return true;
11732 if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
11733 if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11734 Changed = ChangeStatus::CHANGED;
11735 return true;
11736 };
11737 bool UsedAssumedInformation = false;
11738 (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11739 UsedAssumedInformation,
11740 /* CheckBBLivenessOnly */ true);
11741 return Changed;
11742 }
11743
11744 ChangeStatus indicatePessimisticFixpoint() override {
11745 return AAPotentialValues::indicatePessimisticFixpoint();
11746 }
11747
11748 /// See AbstractAttribute::trackStatistics()
11749 void trackStatistics() const override{
11750 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11751
11752 /// The argumented with an existing `returned` attribute.
11753 Argument *ReturnedArg = nullptr;
11754};
11755
11756struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11757 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11758 : AAPotentialValuesImpl(IRP, A) {}
11759
11760 /// See AbstractAttribute::updateImpl(...).
11761 ChangeStatus updateImpl(Attributor &A) override {
11762 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11763 "not be called");
11764 }
11765
11766 /// See AbstractAttribute::trackStatistics()
11767 void trackStatistics() const override {
11768 STATS_DECLTRACK_FN_ATTR(potential_values)
11769 }
11770};
11771
11772struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11773 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11774 : AAPotentialValuesFunction(IRP, A) {}
11775
11776 /// See AbstractAttribute::trackStatistics()
11777 void trackStatistics() const override {
11778 STATS_DECLTRACK_CS_ATTR(potential_values)
11779 }
11780};
11781
11782struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11783 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11784 : AAPotentialValuesImpl(IRP, A) {}
11785
11786 /// See AbstractAttribute::updateImpl(...).
11787 ChangeStatus updateImpl(Attributor &A) override {
11788 auto AssumedBefore = getAssumed();
11789
11790 Function *Callee = getAssociatedFunction();
11791 if (!Callee)
11792 return indicatePessimisticFixpoint();
11793
11794 bool UsedAssumedInformation = false;
11795 auto *CB = cast<CallBase>(getCtxI());
11796 if (CB->isMustTailCall() &&
11797 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11798 UsedAssumedInformation))
11799 return indicatePessimisticFixpoint();
11800
11801 Function *Caller = CB->getCaller();
11802
11803 auto AddScope = [&](AA::ValueScope S) {
11805 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11806 Values, S, UsedAssumedInformation))
11807 return false;
11808
11809 for (auto &It : Values) {
11810 Value *V = It.getValue();
11811 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11812 V, *CB, *this, UsedAssumedInformation);
11813 if (!CallerV.has_value()) {
11814 // Nothing to do as long as no value was determined.
11815 continue;
11816 }
11817 V = *CallerV ? *CallerV : V;
11818 if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {
11819 if (recurseForValue(A, IRPosition::value(*V), S))
11820 continue;
11821 }
11822 if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {
11823 giveUpOnIntraprocedural(A);
11824 return true;
11825 }
11826 addValue(A, getState(), *V, CB, S, getAnchorScope());
11827 }
11828 return true;
11829 };
11830 if (!AddScope(AA::Intraprocedural))
11831 return indicatePessimisticFixpoint();
11832 if (!AddScope(AA::Interprocedural))
11833 return indicatePessimisticFixpoint();
11834 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11835 : ChangeStatus::CHANGED;
11836 }
11837
11838 ChangeStatus indicatePessimisticFixpoint() override {
11839 return AAPotentialValues::indicatePessimisticFixpoint();
11840 }
11841
11842 /// See AbstractAttribute::trackStatistics()
11843 void trackStatistics() const override {
11844 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11845 }
11846};
11847
11848struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11849 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11850 : AAPotentialValuesFloating(IRP, A) {}
11851
11852 /// See AbstractAttribute::trackStatistics()
11853 void trackStatistics() const override {
11854 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11855 }
11856};
11857} // namespace
11858
11859/// ---------------------- Assumption Propagation ------------------------------
11860namespace {
11861struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11862 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11863 const DenseSet<StringRef> &Known)
11864 : AAAssumptionInfo(IRP, A, Known) {}
11865
11866 /// See AbstractAttribute::manifest(...).
11867 ChangeStatus manifest(Attributor &A) override {
11868 // Don't manifest a universal set if it somehow made it here.
11869 if (getKnown().isUniversal())
11870 return ChangeStatus::UNCHANGED;
11871
11872 const IRPosition &IRP = getIRPosition();
11873 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11874 getAssumed().getSet().end());
11875 llvm::sort(Set);
11876 return A.manifestAttrs(IRP,
11877 Attribute::get(IRP.getAnchorValue().getContext(),
11879 llvm::join(Set, ",")),
11880 /*ForceReplace=*/true);
11881 }
11882
11883 bool hasAssumption(const StringRef Assumption) const override {
11884 return isValidState() && setContains(Assumption);
11885 }
11886
11887 /// See AbstractAttribute::getAsStr()
11888 const std::string getAsStr(Attributor *A) const override {
11889 const SetContents &Known = getKnown();
11890 const SetContents &Assumed = getAssumed();
11891
11892 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11893 llvm::sort(Set);
11894 const std::string KnownStr = llvm::join(Set, ",");
11895
11896 std::string AssumedStr = "Universal";
11897 if (!Assumed.isUniversal()) {
11898 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11899 AssumedStr = llvm::join(Set, ",");
11900 }
11901 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11902 }
11903};
11904
11905/// Propagates assumption information from parent functions to all of their
11906/// successors. An assumption can be propagated if the containing function
11907/// dominates the called function.
11908///
11909/// We start with a "known" set of assumptions already valid for the associated
11910/// function and an "assumed" set that initially contains all possible
11911/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11912/// contents as concrete values are known. The concrete values are seeded by the
11913/// first nodes that are either entries into the call graph, or contains no
11914/// assumptions. Each node is updated as the intersection of the assumed state
11915/// with all of its predecessors.
11916struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11917 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11918 : AAAssumptionInfoImpl(IRP, A,
11919 getAssumptions(*IRP.getAssociatedFunction())) {}
11920
11921 /// See AbstractAttribute::updateImpl(...).
11922 ChangeStatus updateImpl(Attributor &A) override {
11923 bool Changed = false;
11924
11925 auto CallSitePred = [&](AbstractCallSite ACS) {
11926 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11927 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11928 DepClassTy::REQUIRED);
11929 if (!AssumptionAA)
11930 return false;
11931 // Get the set of assumptions shared by all of this function's callers.
11932 Changed |= getIntersection(AssumptionAA->getAssumed());
11933 return !getAssumed().empty() || !getKnown().empty();
11934 };
11935
11936 bool UsedAssumedInformation = false;
11937 // Get the intersection of all assumptions held by this node's predecessors.
11938 // If we don't know all the call sites then this is either an entry into the
11939 // call graph or an empty node. This node is known to only contain its own
11940 // assumptions and can be propagated to its successors.
11941 if (!A.checkForAllCallSites(CallSitePred, *this, true,
11942 UsedAssumedInformation))
11943 return indicatePessimisticFixpoint();
11944
11945 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11946 }
11947
11948 void trackStatistics() const override {}
11949};
11950
11951/// Assumption Info defined for call sites.
11952struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
11953
11954 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
11955 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
11956
11957 /// See AbstractAttribute::initialize(...).
11958 void initialize(Attributor &A) override {
11959 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11960 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11961 }
11962
11963 /// See AbstractAttribute::updateImpl(...).
11964 ChangeStatus updateImpl(Attributor &A) override {
11965 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
11966 auto *AssumptionAA =
11967 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
11968 if (!AssumptionAA)
11969 return indicatePessimisticFixpoint();
11970 bool Changed = getIntersection(AssumptionAA->getAssumed());
11971 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
11972 }
11973
11974 /// See AbstractAttribute::trackStatistics()
11975 void trackStatistics() const override {}
11976
11977private:
11978 /// Helper to initialized the known set as all the assumptions this call and
11979 /// the callee contain.
11980 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
11981 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
11982 auto Assumptions = getAssumptions(CB);
11983 if (const Function *F = CB.getCaller())
11984 set_union(Assumptions, getAssumptions(*F));
11985 if (Function *F = IRP.getAssociatedFunction())
11986 set_union(Assumptions, getAssumptions(*F));
11987 return Assumptions;
11988 }
11989};
11990} // namespace
11991
11993 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
11994 A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
11995}
11996
11998
11999/// ------------------------ UnderlyingObjects ---------------------------------
12000
12001namespace {
12002struct AAUnderlyingObjectsImpl
12003 : StateWrapper<BooleanState, AAUnderlyingObjects> {
12005 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
12006
12007 /// See AbstractAttribute::getAsStr().
12008 const std::string getAsStr(Attributor *A) const override {
12009 if (!isValidState())
12010 return "<invalid>";
12011 std::string Str;
12013 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12014 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
12015 << " objects.\n";
12016 if (!InterAssumedUnderlyingObjects.empty()) {
12017 OS << "inter objects:\n";
12018 for (auto *Obj : InterAssumedUnderlyingObjects)
12019 OS << *Obj << '\n';
12020 }
12021 if (!IntraAssumedUnderlyingObjects.empty()) {
12022 OS << "intra objects:\n";
12023 for (auto *Obj : IntraAssumedUnderlyingObjects)
12024 OS << *Obj << '\n';
12025 }
12026 return Str;
12027 }
12028
12029 /// See AbstractAttribute::trackStatistics()
12030 void trackStatistics() const override {}
12031
12032 /// See AbstractAttribute::updateImpl(...).
12033 ChangeStatus updateImpl(Attributor &A) override {
12034 auto &Ptr = getAssociatedValue();
12035
12036 bool UsedAssumedInformation = false;
12037 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12039 SmallPtrSet<Value *, 8> SeenObjects;
12041
12042 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
12043 Scope, UsedAssumedInformation))
12044 return UnderlyingObjects.insert(&Ptr);
12045
12046 bool Changed = false;
12047
12048 for (unsigned I = 0; I < Values.size(); ++I) {
12049 auto &VAC = Values[I];
12050 auto *Obj = VAC.getValue();
12051 Value *UO = getUnderlyingObject(Obj);
12052 if (!SeenObjects.insert(UO ? UO : Obj).second)
12053 continue;
12054 if (UO && UO != Obj) {
12055 if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {
12056 Changed |= UnderlyingObjects.insert(UO);
12057 continue;
12058 }
12059
12060 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
12061 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
12062 auto Pred = [&](Value &V) {
12063 if (&V == UO)
12064 Changed |= UnderlyingObjects.insert(UO);
12065 else
12066 Values.emplace_back(V, nullptr);
12067 return true;
12068 };
12069
12070 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12072 "The forall call should not return false at this position");
12073 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
12074 continue;
12075 }
12076
12077 if (isa<SelectInst>(Obj)) {
12078 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,
12079 UsedAssumedInformation);
12080 continue;
12081 }
12082 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
12083 // Explicitly look through PHIs as we do not care about dynamically
12084 // uniqueness.
12085 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
12086 Changed |=
12087 handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,
12088 Scope, UsedAssumedInformation);
12089 }
12090 continue;
12091 }
12092
12093 Changed |= UnderlyingObjects.insert(Obj);
12094 }
12095
12096 return Changed;
12097 };
12098
12099 bool Changed = false;
12100 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
12101 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
12102 if (!UsedAssumedInformation)
12103 indicateOptimisticFixpoint();
12104 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12105 }
12106
12107 bool forallUnderlyingObjects(
12108 function_ref<bool(Value &)> Pred,
12109 AA::ValueScope Scope = AA::Interprocedural) const override {
12110 if (!isValidState())
12111 return Pred(getAssociatedValue());
12112
12113 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
12114 ? IntraAssumedUnderlyingObjects
12115 : InterAssumedUnderlyingObjects;
12116 for (Value *Obj : AssumedUnderlyingObjects)
12117 if (!Pred(*Obj))
12118 return false;
12119
12120 return true;
12121 }
12122
12123private:
12124 /// Handle the case where the value is not the actual underlying value, such
12125 /// as a phi node or a select instruction.
12126 bool handleIndirect(Attributor &A, Value &V,
12127 SmallSetVector<Value *, 8> &UnderlyingObjects,
12128 AA::ValueScope Scope, bool &UsedAssumedInformation) {
12129 bool Changed = false;
12130 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
12131 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
12132 auto Pred = [&](Value &V) {
12133 Changed |= UnderlyingObjects.insert(&V);
12134 return true;
12135 };
12136 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12138 "The forall call should not return false at this position");
12139 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
12140 return Changed;
12141 }
12142
12143 /// All the underlying objects collected so far via intra procedural scope.
12144 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12145 /// All the underlying objects collected so far via inter procedural scope.
12146 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12147};
12148
12149struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12150 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
12151 : AAUnderlyingObjectsImpl(IRP, A) {}
12152};
12153
12154struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12155 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
12156 : AAUnderlyingObjectsImpl(IRP, A) {}
12157};
12158
12159struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12160 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
12161 : AAUnderlyingObjectsImpl(IRP, A) {}
12162};
12163
12164struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12165 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
12166 : AAUnderlyingObjectsImpl(IRP, A) {}
12167};
12168
12169struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12170 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
12171 : AAUnderlyingObjectsImpl(IRP, A) {}
12172};
12173
12174struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12175 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
12176 : AAUnderlyingObjectsImpl(IRP, A) {}
12177};
12178
12179struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12180 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
12181 : AAUnderlyingObjectsImpl(IRP, A) {}
12182};
12183} // namespace
12184
12185/// ------------------------ Global Value Info -------------------------------
12186namespace {
12187struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12188 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12189 : AAGlobalValueInfo(IRP, A) {}
12190
12191 /// See AbstractAttribute::initialize(...).
12192 void initialize(Attributor &A) override {}
12193
12194 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12195 SmallVectorImpl<const Value *> &Worklist) {
12196 Instruction *UInst = dyn_cast<Instruction>(U.getUser());
12197 if (!UInst) {
12198 Follow = true;
12199 return true;
12200 }
12201
12202 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12203 << *UInst << "\n");
12204
12205 if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {
12206 int Idx = &Cmp->getOperandUse(0) == &U;
12207 if (isa<Constant>(Cmp->getOperand(Idx)))
12208 return true;
12209 return U == &getAnchorValue();
12210 }
12211
12212 // Explicitly catch return instructions.
12213 if (isa<ReturnInst>(UInst)) {
12214 auto CallSitePred = [&](AbstractCallSite ACS) {
12215 Worklist.push_back(ACS.getInstruction());
12216 return true;
12217 };
12218 bool UsedAssumedInformation = false;
12219 // TODO: We should traverse the uses or add a "non-call-site" CB.
12220 if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),
12221 /*RequireAllCallSites=*/true, this,
12222 UsedAssumedInformation))
12223 return false;
12224 return true;
12225 }
12226
12227 // For now we only use special logic for call sites. However, the tracker
12228 // itself knows about a lot of other non-capturing cases already.
12229 auto *CB = dyn_cast<CallBase>(UInst);
12230 if (!CB)
12231 return false;
12232 // Direct calls are OK uses.
12233 if (CB->isCallee(&U))
12234 return true;
12235 // Non-argument uses are scary.
12236 if (!CB->isArgOperand(&U))
12237 return false;
12238 // TODO: Iterate callees.
12239 auto *Fn = dyn_cast<Function>(CB->getCalledOperand());
12240 if (!Fn || !A.isFunctionIPOAmendable(*Fn))
12241 return false;
12242
12243 unsigned ArgNo = CB->getArgOperandNo(&U);
12244 Worklist.push_back(Fn->getArg(ArgNo));
12245 return true;
12246 }
12247
12248 ChangeStatus updateImpl(Attributor &A) override {
12249 unsigned NumUsesBefore = Uses.size();
12250
12251 SmallPtrSet<const Value *, 8> Visited;
12253 Worklist.push_back(&getAnchorValue());
12254
12255 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12256 Uses.insert(&U);
12257 // TODO(captures): Make this more precise.
12258 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12259 if (CI.isPassthrough()) {
12260 Follow = true;
12261 return true;
12262 }
12263 return checkUse(A, U, Follow, Worklist);
12264 };
12265 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12266 Uses.insert(&OldU);
12267 return true;
12268 };
12269
12270 while (!Worklist.empty()) {
12271 const Value *V = Worklist.pop_back_val();
12272 if (!Visited.insert(V).second)
12273 continue;
12274 if (!A.checkForAllUses(UsePred, *this, *V,
12275 /* CheckBBLivenessOnly */ true,
12276 DepClassTy::OPTIONAL,
12277 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12278 return indicatePessimisticFixpoint();
12279 }
12280 }
12281
12282 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12283 : ChangeStatus::CHANGED;
12284 }
12285
12286 bool isPotentialUse(const Use &U) const override {
12287 return !isValidState() || Uses.contains(&U);
12288 }
12289
12290 /// See AbstractAttribute::manifest(...).
12291 ChangeStatus manifest(Attributor &A) override {
12292 return ChangeStatus::UNCHANGED;
12293 }
12294
12295 /// See AbstractAttribute::getAsStr().
12296 const std::string getAsStr(Attributor *A) const override {
12297 return "[" + std::to_string(Uses.size()) + " uses]";
12298 }
12299
12300 void trackStatistics() const override {
12301 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12302 }
12303
12304private:
12305 /// Set of (transitive) uses of this GlobalValue.
12306 SmallPtrSet<const Use *, 8> Uses;
12307};
12308} // namespace
12309
12310/// ------------------------ Indirect Call Info -------------------------------
12311namespace {
12312struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12313 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12314 : AAIndirectCallInfo(IRP, A) {}
12315
12316 /// See AbstractAttribute::initialize(...).
12317 void initialize(Attributor &A) override {
12318 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12319 if (!MD && !A.isClosedWorldModule())
12320 return;
12321
12322 if (MD) {
12323 for (const auto &Op : MD->operands())
12324 if (Function *Callee = mdconst::dyn_extract_or_null<Function>(Op))
12325 PotentialCallees.insert(Callee);
12326 } else if (A.isClosedWorldModule()) {
12327 ArrayRef<Function *> IndirectlyCallableFunctions =
12328 A.getInfoCache().getIndirectlyCallableFunctions(A);
12329 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12330 }
12331
12332 if (PotentialCallees.empty())
12333 indicateOptimisticFixpoint();
12334 }
12335
12336 ChangeStatus updateImpl(Attributor &A) override {
12337 CallBase *CB = cast<CallBase>(getCtxI());
12338 const Use &CalleeUse = CB->getCalledOperandUse();
12339 Value *FP = CB->getCalledOperand();
12340
12341 SmallSetVector<Function *, 4> AssumedCalleesNow;
12342 bool AllCalleesKnownNow = AllCalleesKnown;
12343
12344 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12345 bool &UsedAssumedInformation) {
12346 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12347 *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);
12348 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12349 return true;
12350 UsedAssumedInformation = !GIAA->isAtFixpoint();
12351 return false;
12352 };
12353
12354 auto AddPotentialCallees = [&]() {
12355 for (auto *PotentialCallee : PotentialCallees) {
12356 bool UsedAssumedInformation = false;
12357 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12358 AssumedCalleesNow.insert(PotentialCallee);
12359 }
12360 };
12361
12362 // Use simplification to find potential callees, if !callees was present,
12363 // fallback to that set if necessary.
12364 bool UsedAssumedInformation = false;
12366 if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,
12367 AA::ValueScope::AnyScope,
12368 UsedAssumedInformation)) {
12369 if (PotentialCallees.empty())
12370 return indicatePessimisticFixpoint();
12371 AddPotentialCallees();
12372 }
12373
12374 // Try to find a reason for \p Fn not to be a potential callee. If none was
12375 // found, add it to the assumed callees set.
12376 auto CheckPotentialCallee = [&](Function &Fn) {
12377 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12378 return false;
12379
12380 auto &CachedResult = FilterResults[&Fn];
12381 if (CachedResult.has_value())
12382 return CachedResult.value();
12383
12384 bool UsedAssumedInformation = false;
12385 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12386 if (!UsedAssumedInformation)
12387 CachedResult = false;
12388 return false;
12389 }
12390
12391 int NumFnArgs = Fn.arg_size();
12392 int NumCBArgs = CB->arg_size();
12393
12394 // Check if any excess argument (which we fill up with poison) is known to
12395 // be UB on undef.
12396 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12397 bool IsKnown = false;
12399 A, this, IRPosition::argument(*Fn.getArg(I)),
12400 DepClassTy::OPTIONAL, IsKnown)) {
12401 if (IsKnown)
12402 CachedResult = false;
12403 return false;
12404 }
12405 }
12406
12407 CachedResult = true;
12408 return true;
12409 };
12410
12411 // Check simplification result, prune known UB callees, also restrict it to
12412 // the !callees set, if present.
12413 for (auto &VAC : Values) {
12414 if (isa<UndefValue>(VAC.getValue()))
12415 continue;
12417 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12418 continue;
12419 // TODO: Check for known UB, e.g., poison + noundef.
12420 if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {
12421 if (CheckPotentialCallee(*VACFn))
12422 AssumedCalleesNow.insert(VACFn);
12423 continue;
12424 }
12425 if (!PotentialCallees.empty()) {
12426 AddPotentialCallees();
12427 break;
12428 }
12429 AllCalleesKnownNow = false;
12430 }
12431
12432 if (AssumedCalleesNow == AssumedCallees &&
12433 AllCalleesKnown == AllCalleesKnownNow)
12434 return ChangeStatus::UNCHANGED;
12435
12436 std::swap(AssumedCallees, AssumedCalleesNow);
12437 AllCalleesKnown = AllCalleesKnownNow;
12438 return ChangeStatus::CHANGED;
12439 }
12440
12441 /// See AbstractAttribute::manifest(...).
12442 ChangeStatus manifest(Attributor &A) override {
12443 // If we can't specialize at all, give up now.
12444 if (!AllCalleesKnown && AssumedCallees.empty())
12445 return ChangeStatus::UNCHANGED;
12446
12447 CallBase *CB = cast<CallBase>(getCtxI());
12448 bool UsedAssumedInformation = false;
12449 if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,
12450 UsedAssumedInformation))
12451 return ChangeStatus::UNCHANGED;
12452
12453 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12454 Value *FP = CB->getCalledOperand();
12455 if (FP->getType()->getPointerAddressSpace())
12456 FP = new AddrSpaceCastInst(FP, PointerType::get(FP->getContext(), 0),
12457 FP->getName() + ".as0", CB->getIterator());
12458
12459 bool CBIsVoid = CB->getType()->isVoidTy();
12461 FunctionType *CSFT = CB->getFunctionType();
12462 SmallVector<Value *> CSArgs(CB->args());
12463
12464 // If we know all callees and there are none, the call site is (effectively)
12465 // dead (or UB).
12466 if (AssumedCallees.empty()) {
12467 assert(AllCalleesKnown &&
12468 "Expected all callees to be known if there are none.");
12469 A.changeToUnreachableAfterManifest(CB);
12470 return ChangeStatus::CHANGED;
12471 }
12472
12473 // Special handling for the single callee case.
12474 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12475 auto *NewCallee = AssumedCallees.front();
12476 if (isLegalToPromote(*CB, NewCallee)) {
12477 promoteCall(*CB, NewCallee, nullptr);
12478 NumIndirectCallsPromoted++;
12479 return ChangeStatus::CHANGED;
12480 }
12481 Instruction *NewCall =
12482 CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12483 CB->getName(), CB->getIterator());
12484 if (!CBIsVoid)
12485 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
12486 A.deleteAfterManifest(*CB);
12487 return ChangeStatus::CHANGED;
12488 }
12489
12490 // For each potential value we create a conditional
12491 //
12492 // ```
12493 // if (ptr == value) value(args);
12494 // else ...
12495 // ```
12496 //
12497 bool SpecializedForAnyCallees = false;
12498 bool SpecializedForAllCallees = AllCalleesKnown;
12499 ICmpInst *LastCmp = nullptr;
12500 SmallVector<Function *, 8> SkippedAssumedCallees;
12502 for (Function *NewCallee : AssumedCallees) {
12503 if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
12504 AssumedCallees.size())) {
12505 SkippedAssumedCallees.push_back(NewCallee);
12506 SpecializedForAllCallees = false;
12507 continue;
12508 }
12509 SpecializedForAnyCallees = true;
12510
12511 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12512 Instruction *ThenTI =
12513 SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);
12514 BasicBlock *CBBB = CB->getParent();
12515 A.registerManifestAddedBasicBlock(*ThenTI->getParent());
12516 A.registerManifestAddedBasicBlock(*IP->getParent());
12517 auto *SplitTI = cast<BranchInst>(LastCmp->getNextNode());
12518 BasicBlock *ElseBB;
12519 if (&*IP == CB) {
12520 ElseBB = BasicBlock::Create(ThenTI->getContext(), "",
12521 ThenTI->getFunction(), CBBB);
12522 A.registerManifestAddedBasicBlock(*ElseBB);
12523 IP = BranchInst::Create(CBBB, ElseBB)->getIterator();
12524 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12525 } else {
12526 ElseBB = IP->getParent();
12527 ThenTI->replaceUsesOfWith(ElseBB, CBBB);
12528 }
12529 CastInst *RetBC = nullptr;
12530 CallInst *NewCall = nullptr;
12531 if (isLegalToPromote(*CB, NewCallee)) {
12532 auto *CBClone = cast<CallBase>(CB->clone());
12533 CBClone->insertBefore(ThenTI->getIterator());
12534 NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
12535 NumIndirectCallsPromoted++;
12536 } else {
12537 NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12538 CB->getName(), ThenTI->getIterator());
12539 }
12540 NewCalls.push_back({NewCall, RetBC});
12541 }
12542
12543 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12544 if (!AllCalleesKnown)
12545 return ChangeStatus::UNCHANGED;
12546 MDBuilder MDB(IndirectCB.getContext());
12547 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12548 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12549 return ChangeStatus::CHANGED;
12550 };
12551
12552 if (!SpecializedForAnyCallees)
12553 return AttachCalleeMetadata(*CB);
12554
12555 // Check if we need the fallback indirect call still.
12556 if (SpecializedForAllCallees) {
12558 LastCmp->eraseFromParent();
12559 new UnreachableInst(IP->getContext(), IP);
12560 IP->eraseFromParent();
12561 } else {
12562 auto *CBClone = cast<CallInst>(CB->clone());
12563 CBClone->setName(CB->getName());
12564 CBClone->insertBefore(*IP->getParent(), IP);
12565 NewCalls.push_back({CBClone, nullptr});
12566 AttachCalleeMetadata(*CBClone);
12567 }
12568
12569 // Check if we need a PHI to merge the results.
12570 if (!CBIsVoid) {
12571 auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),
12572 CB->getName() + ".phi",
12573 CB->getParent()->getFirstInsertionPt());
12574 for (auto &It : NewCalls) {
12575 CallBase *NewCall = It.first;
12576 Instruction *CallRet = It.second ? It.second : It.first;
12577 if (CallRet->getType() == CB->getType())
12578 PHI->addIncoming(CallRet, CallRet->getParent());
12579 else if (NewCall->getType()->isVoidTy())
12580 PHI->addIncoming(PoisonValue::get(CB->getType()),
12581 NewCall->getParent());
12582 else
12583 llvm_unreachable("Call return should match or be void!");
12584 }
12585 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);
12586 }
12587
12588 A.deleteAfterManifest(*CB);
12589 Changed = ChangeStatus::CHANGED;
12590
12591 return Changed;
12592 }
12593
12594 /// See AbstractAttribute::getAsStr().
12595 const std::string getAsStr(Attributor *A) const override {
12596 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12597 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12598 " functions";
12599 }
12600
12601 void trackStatistics() const override {
12602 if (AllCalleesKnown) {
12604 Eliminated, CallSites,
12605 "Number of indirect call sites eliminated via specialization")
12606 } else {
12607 STATS_DECLTRACK(Specialized, CallSites,
12608 "Number of indirect call sites specialized")
12609 }
12610 }
12611
12612 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12613 return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);
12614 }
12615
12616private:
12617 /// Map to remember filter results.
12618 DenseMap<Function *, std::optional<bool>> FilterResults;
12619
12620 /// If the !callee metadata was present, this set will contain all potential
12621 /// callees (superset).
12622 SmallSetVector<Function *, 4> PotentialCallees;
12623
12624 /// This set contains all currently assumed calllees, which might grow over
12625 /// time.
12626 SmallSetVector<Function *, 4> AssumedCallees;
12627
12628 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12629 /// if there could be others.
12630 bool AllCalleesKnown = true;
12631};
12632} // namespace
12633
12634/// --------------------- Invariant Load Pointer -------------------------------
12635namespace {
12636
12637struct AAInvariantLoadPointerImpl
12638 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12639 AAInvariantLoadPointer> {
12640
12641 enum {
12642 // pointer does not alias within the bounds of the function
12643 IS_NOALIAS = 1 << 0,
12644 // pointer is not involved in any effectful instructions within the bounds
12645 // of the function
12646 IS_NOEFFECT = 1 << 1,
12647 // loads are invariant within the bounds of the function
12648 IS_LOCALLY_INVARIANT = 1 << 2,
12649 // memory lifetime is constrained within the bounds of the function
12650 IS_LOCALLY_CONSTRAINED = 1 << 3,
12651
12652 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12653 IS_LOCALLY_CONSTRAINED,
12654 };
12655 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12656
12657 using Base =
12658 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12659
12660 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12661 // pessimistic about IS_KNOWN_INVARIANT
12662 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12663 : Base(IRP) {}
12664
12665 bool isKnownInvariant() const final {
12666 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12667 }
12668
12669 bool isKnownLocallyInvariant() const final {
12670 if (isKnown(IS_LOCALLY_INVARIANT))
12671 return true;
12672 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12673 }
12674
12675 bool isAssumedInvariant() const final {
12676 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12677 }
12678
12679 bool isAssumedLocallyInvariant() const final {
12680 if (isAssumed(IS_LOCALLY_INVARIANT))
12681 return true;
12682 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12683 }
12684
12685 ChangeStatus updateImpl(Attributor &A) override {
12686 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12687
12688 Changed |= updateNoAlias(A);
12689 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12690 return indicatePessimisticFixpoint();
12691
12692 Changed |= updateNoEffect(A);
12693
12694 Changed |= updateLocalInvariance(A);
12695
12696 return Changed;
12697 }
12698
12699 ChangeStatus manifest(Attributor &A) override {
12700 if (!isKnownInvariant())
12701 return ChangeStatus::UNCHANGED;
12702
12703 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12704 const Value *Ptr = &getAssociatedValue();
12705 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12706 if (U.get() != Ptr)
12707 return true;
12708 auto *I = dyn_cast<Instruction>(U.getUser());
12709 if (!I)
12710 return true;
12711
12712 // Ensure that we are only changing uses from the corresponding callgraph
12713 // SSC in the case that the AA isn't run on the entire module
12714 if (!A.isRunOn(I->getFunction()))
12715 return true;
12716
12717 if (I->hasMetadata(LLVMContext::MD_invariant_load))
12718 return true;
12719
12720 if (auto *LI = dyn_cast<LoadInst>(I)) {
12721 LI->setMetadata(LLVMContext::MD_invariant_load,
12722 MDNode::get(LI->getContext(), {}));
12723 Changed = ChangeStatus::CHANGED;
12724 }
12725 return true;
12726 };
12727
12728 (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);
12729 return Changed;
12730 }
12731
12732 /// See AbstractAttribute::getAsStr().
12733 const std::string getAsStr(Attributor *) const override {
12734 if (isKnownInvariant())
12735 return "load-invariant pointer";
12736 return "non-invariant pointer";
12737 }
12738
12739 /// See AbstractAttribute::trackStatistics().
12740 void trackStatistics() const override {}
12741
12742private:
12743 /// Indicate that noalias is required for the pointer to be invariant.
12744 bool requiresNoAlias() const {
12745 switch (getPositionKind()) {
12746 default:
12747 // Conservatively default to require noalias.
12748 return true;
12749 case IRP_FLOAT:
12750 case IRP_RETURNED:
12751 case IRP_CALL_SITE:
12752 return false;
12753 case IRP_CALL_SITE_RETURNED: {
12754 const auto &CB = cast<CallBase>(getAnchorValue());
12756 &CB, /*MustPreserveNullness=*/false);
12757 }
12758 case IRP_ARGUMENT: {
12759 const Function *F = getAssociatedFunction();
12760 assert(F && "no associated function for argument");
12761 return !isCallableCC(F->getCallingConv());
12762 }
12763 }
12764 }
12765
12766 bool isExternal() const {
12767 const Function *F = getAssociatedFunction();
12768 if (!F)
12769 return true;
12770 return isCallableCC(F->getCallingConv()) &&
12771 getPositionKind() != IRP_CALL_SITE_RETURNED;
12772 }
12773
12774 ChangeStatus updateNoAlias(Attributor &A) {
12775 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12776 return ChangeStatus::UNCHANGED;
12777
12778 // Try to use AANoAlias.
12779 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12780 getIRPosition(), this, DepClassTy::REQUIRED)) {
12781 if (ANoAlias->isKnownNoAlias()) {
12782 addKnownBits(IS_NOALIAS);
12783 return ChangeStatus::CHANGED;
12784 }
12785
12786 if (!ANoAlias->isAssumedNoAlias()) {
12787 removeAssumedBits(IS_NOALIAS);
12788 return ChangeStatus::CHANGED;
12789 }
12790
12791 return ChangeStatus::UNCHANGED;
12792 }
12793
12794 // Try to infer noalias from argument attribute, since it is applicable for
12795 // the duration of the function.
12796 if (const Argument *Arg = getAssociatedArgument()) {
12797 if (Arg->hasNoAliasAttr()) {
12798 addKnownBits(IS_NOALIAS);
12799 return ChangeStatus::UNCHANGED;
12800 }
12801
12802 // Noalias information is not provided, and cannot be inferred,
12803 // so we conservatively assume the pointer aliases.
12804 removeAssumedBits(IS_NOALIAS);
12805 return ChangeStatus::CHANGED;
12806 }
12807
12808 return ChangeStatus::UNCHANGED;
12809 }
12810
12811 ChangeStatus updateNoEffect(Attributor &A) {
12812 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12813 return ChangeStatus::UNCHANGED;
12814
12815 if (!getAssociatedFunction())
12816 return indicatePessimisticFixpoint();
12817
12818 if (isa<AllocaInst>(&getAssociatedValue()))
12819 return indicatePessimisticFixpoint();
12820
12821 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12822 const auto *LI = dyn_cast<LoadInst>(U.getUser());
12823 return !LI || !LI->mayHaveSideEffects();
12824 };
12825 if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))
12826 return indicatePessimisticFixpoint();
12827
12828 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12829 getIRPosition(), this, DepClassTy::REQUIRED)) {
12830 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12831 // attribute
12832 if (!AMemoryBehavior->isAssumedReadOnly())
12833 return indicatePessimisticFixpoint();
12834
12835 if (AMemoryBehavior->isKnownReadOnly()) {
12836 addKnownBits(IS_NOEFFECT);
12837 return ChangeStatus::UNCHANGED;
12838 }
12839
12840 return ChangeStatus::UNCHANGED;
12841 }
12842
12843 if (const Argument *Arg = getAssociatedArgument()) {
12844 if (Arg->onlyReadsMemory()) {
12845 addKnownBits(IS_NOEFFECT);
12846 return ChangeStatus::UNCHANGED;
12847 }
12848
12849 // Readonly information is not provided, and cannot be inferred from
12850 // AAMemoryBehavior.
12851 return indicatePessimisticFixpoint();
12852 }
12853
12854 return ChangeStatus::UNCHANGED;
12855 }
12856
12857 ChangeStatus updateLocalInvariance(Attributor &A) {
12858 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12859 return ChangeStatus::UNCHANGED;
12860
12861 // try to infer invariance from underlying objects
12862 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12863 getIRPosition(), this, DepClassTy::REQUIRED);
12864 if (!AUO)
12865 return ChangeStatus::UNCHANGED;
12866
12867 bool UsedAssumedInformation = false;
12868 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12869 if (!V.getType()->isPointerTy())
12870 return true;
12871 const auto *IsInvariantLoadPointer =
12872 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,
12873 DepClassTy::REQUIRED);
12874 // Conservatively fail if invariance cannot be inferred.
12875 if (!IsInvariantLoadPointer)
12876 return false;
12877
12878 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12879 return true;
12880 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12881 return false;
12882
12883 UsedAssumedInformation = true;
12884 return true;
12885 };
12886 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12887 return indicatePessimisticFixpoint();
12888
12889 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {
12891 CB, /*MustPreserveNullness=*/false)) {
12892 for (const Value *Arg : CB->args()) {
12893 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12894 return indicatePessimisticFixpoint();
12895 }
12896 }
12897 }
12898
12899 if (!UsedAssumedInformation) {
12900 // Pointer is known and not just assumed to be locally invariant.
12901 addKnownBits(IS_LOCALLY_INVARIANT);
12902 return ChangeStatus::CHANGED;
12903 }
12904
12905 return ChangeStatus::UNCHANGED;
12906 }
12907};
12908
12909struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12910 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12911 : AAInvariantLoadPointerImpl(IRP, A) {}
12912};
12913
12914struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12915 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12916 : AAInvariantLoadPointerImpl(IRP, A) {}
12917
12918 void initialize(Attributor &) override {
12919 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12920 }
12921};
12922
12923struct AAInvariantLoadPointerCallSiteReturned final
12924 : AAInvariantLoadPointerImpl {
12925 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12926 : AAInvariantLoadPointerImpl(IRP, A) {}
12927
12928 void initialize(Attributor &A) override {
12929 const Function *F = getAssociatedFunction();
12930 assert(F && "no associated function for return from call");
12931
12932 if (!F->isDeclaration() && !F->isIntrinsic())
12933 return AAInvariantLoadPointerImpl::initialize(A);
12934
12935 const auto &CB = cast<CallBase>(getAnchorValue());
12937 &CB, /*MustPreserveNullness=*/false))
12938 return AAInvariantLoadPointerImpl::initialize(A);
12939
12940 if (F->onlyReadsMemory() && F->hasNoSync())
12941 return AAInvariantLoadPointerImpl::initialize(A);
12942
12943 // At this point, the function is opaque, so we conservatively assume
12944 // non-invariance.
12945 indicatePessimisticFixpoint();
12946 }
12947};
12948
12949struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
12950 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
12951 : AAInvariantLoadPointerImpl(IRP, A) {}
12952
12953 void initialize(Attributor &) override {
12954 const Function *F = getAssociatedFunction();
12955 assert(F && "no associated function for argument");
12956
12957 if (!isCallableCC(F->getCallingConv())) {
12958 addKnownBits(IS_LOCALLY_CONSTRAINED);
12959 return;
12960 }
12961
12962 if (!F->hasLocalLinkage())
12963 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12964 }
12965};
12966
12967struct AAInvariantLoadPointerCallSiteArgument final
12968 : AAInvariantLoadPointerImpl {
12969 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
12970 : AAInvariantLoadPointerImpl(IRP, A) {}
12971};
12972} // namespace
12973
12974/// ------------------------ Address Space ------------------------------------
12975namespace {
12976
12977template <typename InstType>
12978static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
12979 Value *OriginalValue, PointerType *NewPtrTy,
12980 bool UseOriginalValue) {
12981 if (U.getOperandNo() != InstType::getPointerOperandIndex())
12982 return false;
12983
12984 if (MemInst->isVolatile()) {
12985 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
12986 *MemInst->getFunction());
12987 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
12988 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
12989 return false;
12990 }
12991
12992 if (UseOriginalValue) {
12993 A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);
12994 return true;
12995 }
12996
12997 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
12998 CastInst->insertBefore(MemInst->getIterator());
12999 A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);
13000 return true;
13001}
13002
13003struct AAAddressSpaceImpl : public AAAddressSpace {
13004 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
13005 : AAAddressSpace(IRP, A) {}
13006
13007 uint32_t getAddressSpace() const override {
13008 assert(isValidState() && "the AA is invalid");
13009 return AssumedAddressSpace;
13010 }
13011
13012 /// See AbstractAttribute::initialize(...).
13013 void initialize(Attributor &A) override {
13014 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13015 "Associated value is not a pointer");
13016
13017 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
13018 indicatePessimisticFixpoint();
13019 return;
13020 }
13021
13022 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13023 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13024 if (AS != FlatAS) {
13025 [[maybe_unused]] bool R = takeAddressSpace(AS);
13026 assert(R && "The take should happen");
13027 indicateOptimisticFixpoint();
13028 }
13029 }
13030
13031 ChangeStatus updateImpl(Attributor &A) override {
13032 uint32_t OldAddressSpace = AssumedAddressSpace;
13033 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13034
13035 auto CheckAddressSpace = [&](Value &Obj) {
13036 // Ignore undef.
13037 if (isa<UndefValue>(&Obj))
13038 return true;
13039
13040 // If the object already has a non-flat address space, we simply take it.
13041 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
13042 if (ObjAS != FlatAS)
13043 return takeAddressSpace(ObjAS);
13044
13045 // At this point, we know Obj is in the flat address space. For a final
13046 // attempt, we want to use getAssumedAddrSpace, but first we must get the
13047 // associated function, if possible.
13048 Function *F = nullptr;
13049 if (auto *Arg = dyn_cast<Argument>(&Obj))
13050 F = Arg->getParent();
13051 else if (auto *I = dyn_cast<Instruction>(&Obj))
13052 F = I->getFunction();
13053
13054 // Use getAssumedAddrSpace if the associated function exists.
13055 if (F) {
13056 auto *TTI =
13057 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13058 unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);
13059 if (AssumedAS != ~0U)
13060 return takeAddressSpace(AssumedAS);
13061 }
13062
13063 // Now we can't do anything else but to take the flat AS.
13064 return takeAddressSpace(FlatAS);
13065 };
13066
13067 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
13068 DepClassTy::REQUIRED);
13069 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13070 return indicatePessimisticFixpoint();
13071
13072 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13073 : ChangeStatus::CHANGED;
13074 }
13075
13076 /// See AbstractAttribute::manifest(...).
13077 ChangeStatus manifest(Attributor &A) override {
13078 unsigned NewAS = getAddressSpace();
13079
13080 if (NewAS == InvalidAddressSpace ||
13081 NewAS == getAssociatedType()->getPointerAddressSpace())
13082 return ChangeStatus::UNCHANGED;
13083
13084 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13085
13086 Value *AssociatedValue = &getAssociatedValue();
13087 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13088
13089 PointerType *NewPtrTy =
13090 PointerType::get(getAssociatedType()->getContext(), NewAS);
13091 bool UseOriginalValue =
13092 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
13093
13094 bool Changed = false;
13095
13096 auto Pred = [&](const Use &U, bool &) {
13097 if (U.get() != AssociatedValue)
13098 return true;
13099 auto *Inst = dyn_cast<Instruction>(U.getUser());
13100 if (!Inst)
13101 return true;
13102 // This is a WA to make sure we only change uses from the corresponding
13103 // CGSCC if the AA is run on CGSCC instead of the entire module.
13104 if (!A.isRunOn(Inst->getFunction()))
13105 return true;
13106 if (auto *LI = dyn_cast<LoadInst>(Inst)) {
13107 Changed |=
13108 makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13109 } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
13110 Changed |=
13111 makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13112 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {
13113 Changed |=
13114 makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13115 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {
13116 Changed |=
13117 makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13118 }
13119 return true;
13120 };
13121
13122 // It doesn't matter if we can't check all uses as we can simply
13123 // conservatively ignore those that can not be visited.
13124 (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
13125 /* CheckBBLivenessOnly */ true);
13126
13127 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13128 }
13129
13130 /// See AbstractAttribute::getAsStr().
13131 const std::string getAsStr(Attributor *A) const override {
13132 if (!isValidState())
13133 return "addrspace(<invalid>)";
13134 return "addrspace(" +
13135 (AssumedAddressSpace == InvalidAddressSpace
13136 ? "none"
13137 : std::to_string(AssumedAddressSpace)) +
13138 ")";
13139 }
13140
13141private:
13142 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13143
13144 bool takeAddressSpace(uint32_t AS) {
13145 if (AssumedAddressSpace == InvalidAddressSpace) {
13146 AssumedAddressSpace = AS;
13147 return true;
13148 }
13149 return AssumedAddressSpace == AS;
13150 }
13151
13152 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
13153 if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {
13154 assert(I->getSrcAddressSpace() != FlatAS &&
13155 "there should not be flat AS -> non-flat AS");
13156 return I->getPointerOperand();
13157 }
13158 if (auto *C = dyn_cast<ConstantExpr>(V))
13159 if (C->getOpcode() == Instruction::AddrSpaceCast) {
13160 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
13161 FlatAS &&
13162 "there should not be flat AS -> non-flat AS X");
13163 return C->getOperand(0);
13164 }
13165 return V;
13166 }
13167};
13168
13169struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13170 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
13171 : AAAddressSpaceImpl(IRP, A) {}
13172
13173 void trackStatistics() const override {
13175 }
13176};
13177
13178struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13179 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
13180 : AAAddressSpaceImpl(IRP, A) {}
13181
13182 /// See AbstractAttribute::initialize(...).
13183 void initialize(Attributor &A) override {
13184 // TODO: we don't rewrite function argument for now because it will need to
13185 // rewrite the function signature and all call sites.
13186 (void)indicatePessimisticFixpoint();
13187 }
13188
13189 void trackStatistics() const override {
13190 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13191 }
13192};
13193
13194struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13195 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13196 : AAAddressSpaceImpl(IRP, A) {}
13197
13198 void trackStatistics() const override {
13199 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13200 }
13201};
13202
13203struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13204 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13205 : AAAddressSpaceImpl(IRP, A) {}
13206
13207 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13208};
13209
13210struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13211 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13212 : AAAddressSpaceImpl(IRP, A) {}
13213
13214 /// See AbstractAttribute::initialize(...).
13215 void initialize(Attributor &A) override {
13216 // TODO: we don't rewrite call site argument for now because it will need to
13217 // rewrite the function signature of the callee.
13218 (void)indicatePessimisticFixpoint();
13219 }
13220
13221 void trackStatistics() const override {
13222 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13223 }
13224};
13225} // namespace
13226
13227/// ------------------------ No Alias Address Space ---------------------------
13228// This attribute assumes flat address space can alias all other address space
13229
13230// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13231// But merging it created failing cased on gateway test that cannot be
13232// reproduced locally. So should open a seperated PR to hande the merge of
13233// AANoAliasAddrSpace and AAAddressSpace attribute
13234
13235namespace {
13236struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13237 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13238 : AANoAliasAddrSpace(IRP, A) {}
13239
13240 void initialize(Attributor &A) override {
13241 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13242 "Associated value is not a pointer");
13243
13244 resetASRanges(A);
13245
13246 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13247 if (!FlatAS.has_value()) {
13248 indicatePessimisticFixpoint();
13249 return;
13250 }
13251
13252 removeAS(*FlatAS);
13253
13254 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13255 if (AS != *FlatAS) {
13256 removeAS(AS);
13257 indicateOptimisticFixpoint();
13258 }
13259 }
13260
13261 ChangeStatus updateImpl(Attributor &A) override {
13262 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13263 uint32_t OldAssumed = getAssumed();
13264
13265 auto CheckAddressSpace = [&](Value &Obj) {
13266 if (isa<PoisonValue>(&Obj))
13267 return true;
13268
13269 unsigned AS = Obj.getType()->getPointerAddressSpace();
13270 if (AS == FlatAS)
13271 return false;
13272
13273 removeAS(Obj.getType()->getPointerAddressSpace());
13274 return true;
13275 };
13276
13277 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13278 getIRPosition(), this, DepClassTy::REQUIRED);
13279 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13280 return indicatePessimisticFixpoint();
13281
13282 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13283 : ChangeStatus::CHANGED;
13284 }
13285
13286 /// See AbstractAttribute::manifest(...).
13287 ChangeStatus manifest(Attributor &A) override {
13288 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13289
13290 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13291 if (AS != FlatAS || Map.empty())
13292 return ChangeStatus::UNCHANGED;
13293
13294 LLVMContext &Ctx = getAssociatedValue().getContext();
13295 MDNode *NoAliasASNode = nullptr;
13296 MDBuilder MDB(Ctx);
13297 // Has to use iterator to get the range info.
13298 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13299 if (!I.value())
13300 continue;
13301 unsigned Upper = I.stop();
13302 unsigned Lower = I.start();
13303 if (!NoAliasASNode) {
13304 NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13305 continue;
13306 }
13307 MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13308 NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13309 }
13310
13311 Value *AssociatedValue = &getAssociatedValue();
13312 bool Changed = false;
13313
13314 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13315 if (U.get() != AssociatedValue)
13316 return true;
13317 Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13318 if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13319 return true;
13320 if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13322 return true;
13323 if (!A.isRunOn(Inst->getFunction()))
13324 return true;
13325 Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13326 Changed = true;
13327 return true;
13328 };
13329 (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13330 /*CheckBBLivenessOnly=*/true);
13331 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13332 }
13333
13334 /// See AbstractAttribute::getAsStr().
13335 const std::string getAsStr(Attributor *A) const override {
13336 if (!isValidState())
13337 return "<invalid>";
13338 std::string Str;
13339 raw_string_ostream OS(Str);
13340 OS << "CanNotBeAddrSpace(";
13341 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13342 unsigned Upper = I.stop();
13343 unsigned Lower = I.start();
13344 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13345 }
13346 OS << " )";
13347 return OS.str();
13348 }
13349
13350private:
13351 void removeAS(unsigned AS) {
13352 RangeMap::iterator I = Map.find(AS);
13353
13354 if (I != Map.end()) {
13355 unsigned Upper = I.stop();
13356 unsigned Lower = I.start();
13357 I.erase();
13358 if (Upper == Lower)
13359 return;
13360 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13361 Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13362 if (AS != 0 && Lower <= AS - 1)
13363 Map.insert(Lower, AS - 1, true);
13364 }
13365 }
13366
13367 void resetASRanges(Attributor &A) {
13368 Map.clear();
13369 Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13370 }
13371};
13372
13373struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13374 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13375 : AANoAliasAddrSpaceImpl(IRP, A) {}
13376
13377 void trackStatistics() const override {
13378 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13379 }
13380};
13381
13382struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13383 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13384 : AANoAliasAddrSpaceImpl(IRP, A) {}
13385
13386 void trackStatistics() const override {
13387 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13388 }
13389};
13390
13391struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13392 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13393 : AANoAliasAddrSpaceImpl(IRP, A) {}
13394
13395 void trackStatistics() const override {
13396 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13397 }
13398};
13399
13400struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13401 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13402 : AANoAliasAddrSpaceImpl(IRP, A) {}
13403
13404 void trackStatistics() const override {
13405 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13406 }
13407};
13408
13409struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13410 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13411 : AANoAliasAddrSpaceImpl(IRP, A) {}
13412
13413 void trackStatistics() const override {
13414 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13415 }
13416};
13417} // namespace
13418/// ----------- Allocation Info ----------
13419namespace {
13420struct AAAllocationInfoImpl : public AAAllocationInfo {
13421 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13422 : AAAllocationInfo(IRP, A) {}
13423
13424 std::optional<TypeSize> getAllocatedSize() const override {
13425 assert(isValidState() && "the AA is invalid");
13426 return AssumedAllocatedSize;
13427 }
13428
13429 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13430 const DataLayout &DL) {
13431
13432 // TODO: implement case for malloc like instructions
13433 switch (I->getOpcode()) {
13434 case Instruction::Alloca: {
13435 AllocaInst *AI = cast<AllocaInst>(I);
13436 return AI->getAllocationSize(DL);
13437 }
13438 default:
13439 return std::nullopt;
13440 }
13441 }
13442
13443 ChangeStatus updateImpl(Attributor &A) override {
13444
13445 const IRPosition &IRP = getIRPosition();
13446 Instruction *I = IRP.getCtxI();
13447
13448 // TODO: update check for malloc like calls
13449 if (!isa<AllocaInst>(I))
13450 return indicatePessimisticFixpoint();
13451
13452 bool IsKnownNoCapture;
13454 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13455 return indicatePessimisticFixpoint();
13456
13457 const AAPointerInfo *PI =
13458 A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);
13459
13460 if (!PI)
13461 return indicatePessimisticFixpoint();
13462
13463 if (!PI->getState().isValidState() || PI->reachesReturn())
13464 return indicatePessimisticFixpoint();
13465
13466 const DataLayout &DL = A.getDataLayout();
13467 const auto AllocationSize = findInitialAllocationSize(I, DL);
13468
13469 // If allocation size is nullopt, we give up.
13470 if (!AllocationSize)
13471 return indicatePessimisticFixpoint();
13472
13473 // For zero sized allocations, we give up.
13474 // Since we can't reduce further
13475 if (*AllocationSize == 0)
13476 return indicatePessimisticFixpoint();
13477
13478 int64_t BinSize = PI->numOffsetBins();
13479
13480 // TODO: implement for multiple bins
13481 if (BinSize > 1)
13482 return indicatePessimisticFixpoint();
13483
13484 if (BinSize == 0) {
13485 auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
13486 if (!changeAllocationSize(NewAllocationSize))
13487 return ChangeStatus::UNCHANGED;
13488 return ChangeStatus::CHANGED;
13489 }
13490
13491 // TODO: refactor this to be part of multiple bin case
13492 const auto &It = PI->begin();
13493
13494 // TODO: handle if Offset is not zero
13495 if (It->first.Offset != 0)
13496 return indicatePessimisticFixpoint();
13497
13498 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13499
13500 if (SizeOfBin >= *AllocationSize)
13501 return indicatePessimisticFixpoint();
13502
13503 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
13504
13505 if (!changeAllocationSize(NewAllocationSize))
13506 return ChangeStatus::UNCHANGED;
13507
13508 return ChangeStatus::CHANGED;
13509 }
13510
13511 /// See AbstractAttribute::manifest(...).
13512 ChangeStatus manifest(Attributor &A) override {
13513
13514 assert(isValidState() &&
13515 "Manifest should only be called if the state is valid.");
13516
13517 Instruction *I = getIRPosition().getCtxI();
13518
13519 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13520
13521 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13522
13523 switch (I->getOpcode()) {
13524 // TODO: add case for malloc like calls
13525 case Instruction::Alloca: {
13526
13527 AllocaInst *AI = cast<AllocaInst>(I);
13528
13529 Type *CharType = Type::getInt8Ty(I->getContext());
13530
13531 auto *NumBytesToValue =
13532 ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));
13533
13534 BasicBlock::iterator insertPt = AI->getIterator();
13535 insertPt = std::next(insertPt);
13536 AllocaInst *NewAllocaInst =
13537 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13538 AI->getAlign(), AI->getName(), insertPt);
13539
13540 if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))
13541 return ChangeStatus::CHANGED;
13542
13543 break;
13544 }
13545 default:
13546 break;
13547 }
13548
13549 return ChangeStatus::UNCHANGED;
13550 }
13551
13552 /// See AbstractAttribute::getAsStr().
13553 const std::string getAsStr(Attributor *A) const override {
13554 if (!isValidState())
13555 return "allocationinfo(<invalid>)";
13556 return "allocationinfo(" +
13557 (AssumedAllocatedSize == HasNoAllocationSize
13558 ? "none"
13559 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13560 ")";
13561 }
13562
13563private:
13564 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13565
13566 // Maintain the computed allocation size of the object.
13567 // Returns (bool) weather the size of the allocation was modified or not.
13568 bool changeAllocationSize(std::optional<TypeSize> Size) {
13569 if (AssumedAllocatedSize == HasNoAllocationSize ||
13570 AssumedAllocatedSize != Size) {
13571 AssumedAllocatedSize = Size;
13572 return true;
13573 }
13574 return false;
13575 }
13576};
13577
13578struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13579 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13580 : AAAllocationInfoImpl(IRP, A) {}
13581
13582 void trackStatistics() const override {
13583 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13584 }
13585};
13586
13587struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13588 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13589 : AAAllocationInfoImpl(IRP, A) {}
13590
13591 /// See AbstractAttribute::initialize(...).
13592 void initialize(Attributor &A) override {
13593 // TODO: we don't rewrite function argument for now because it will need to
13594 // rewrite the function signature and all call sites
13595 (void)indicatePessimisticFixpoint();
13596 }
13597
13598 void trackStatistics() const override {
13599 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13600 }
13601};
13602
13603struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13604 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13605 : AAAllocationInfoImpl(IRP, A) {}
13606
13607 void trackStatistics() const override {
13608 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13609 }
13610};
13611
13612struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13613 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13614 : AAAllocationInfoImpl(IRP, A) {}
13615
13616 void trackStatistics() const override {
13617 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13618 }
13619};
13620
13621struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13622 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13623 : AAAllocationInfoImpl(IRP, A) {}
13624
13625 /// See AbstractAttribute::initialize(...).
13626 void initialize(Attributor &A) override {
13627
13628 (void)indicatePessimisticFixpoint();
13629 }
13630
13631 void trackStatistics() const override {
13632 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13633 }
13634};
13635} // namespace
13636
13637const char AANoUnwind::ID = 0;
13638const char AANoSync::ID = 0;
13639const char AANoFree::ID = 0;
13640const char AANonNull::ID = 0;
13641const char AAMustProgress::ID = 0;
13642const char AANoRecurse::ID = 0;
13643const char AANonConvergent::ID = 0;
13644const char AAWillReturn::ID = 0;
13645const char AAUndefinedBehavior::ID = 0;
13646const char AANoAlias::ID = 0;
13647const char AAIntraFnReachability::ID = 0;
13648const char AANoReturn::ID = 0;
13649const char AAIsDead::ID = 0;
13650const char AADereferenceable::ID = 0;
13651const char AAAlign::ID = 0;
13652const char AAInstanceInfo::ID = 0;
13653const char AANoCapture::ID = 0;
13654const char AAValueSimplify::ID = 0;
13655const char AAHeapToStack::ID = 0;
13656const char AAPrivatizablePtr::ID = 0;
13657const char AAMemoryBehavior::ID = 0;
13658const char AAMemoryLocation::ID = 0;
13659const char AAValueConstantRange::ID = 0;
13660const char AAPotentialConstantValues::ID = 0;
13661const char AAPotentialValues::ID = 0;
13662const char AANoUndef::ID = 0;
13663const char AANoFPClass::ID = 0;
13664const char AACallEdges::ID = 0;
13665const char AAInterFnReachability::ID = 0;
13666const char AAPointerInfo::ID = 0;
13667const char AAAssumptionInfo::ID = 0;
13668const char AAUnderlyingObjects::ID = 0;
13669const char AAInvariantLoadPointer::ID = 0;
13670const char AAAddressSpace::ID = 0;
13671const char AANoAliasAddrSpace::ID = 0;
13672const char AAAllocationInfo::ID = 0;
13673const char AAIndirectCallInfo::ID = 0;
13674const char AAGlobalValueInfo::ID = 0;
13675const char AADenormalFPMath::ID = 0;
13676
13677// Macro magic to create the static generator function for attributes that
13678// follow the naming scheme.
13679
13680#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13681 case IRPosition::PK: \
13682 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13683
13684#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13685 case IRPosition::PK: \
13686 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13687 ++NumAAs; \
13688 break;
13689
13690#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13691 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13692 CLASS *AA = nullptr; \
13693 switch (IRP.getPositionKind()) { \
13694 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13695 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13696 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13697 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13698 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13699 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13700 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13701 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13702 } \
13703 return *AA; \
13704 }
13705
13706#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13707 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13708 CLASS *AA = nullptr; \
13709 switch (IRP.getPositionKind()) { \
13710 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13711 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13712 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13713 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13714 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13715 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13716 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13717 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13718 } \
13719 return *AA; \
13720 }
13721
13722#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13723 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13724 CLASS *AA = nullptr; \
13725 switch (IRP.getPositionKind()) { \
13726 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13727 default: \
13728 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13729 " position!"); \
13730 } \
13731 return *AA; \
13732 }
13733
13734#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13735 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13736 CLASS *AA = nullptr; \
13737 switch (IRP.getPositionKind()) { \
13738 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13739 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13740 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13741 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13742 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13743 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13744 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13745 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13746 } \
13747 return *AA; \
13748 }
13749
13750#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13751 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13752 CLASS *AA = nullptr; \
13753 switch (IRP.getPositionKind()) { \
13754 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13755 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13756 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13757 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13758 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13759 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13760 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13761 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13762 } \
13763 return *AA; \
13764 }
13765
13766#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13767 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13768 CLASS *AA = nullptr; \
13769 switch (IRP.getPositionKind()) { \
13770 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13771 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13772 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13773 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13774 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13775 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13776 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13777 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13778 } \
13779 return *AA; \
13780 }
13781
13791
13809
13814
13819
13826
13828
13829#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13830#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13831#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13832#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13833#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13834#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13835#undef SWITCH_PK_CREATE
13836#undef SWITCH_PK_INV
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
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 DefineKeys(ToTy)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, Cycle **CPtr=nullptr)
#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)
#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< 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)
Definition CFG.cpp:135
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...
DXIL Forward Handle Accesses
DXIL Resource Access
dxil translate DXIL Translate Metadata
This file defines DenseMapInfo traits for DenseMap.
#define Check(C,...)
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)
Basic Register Allocator
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
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
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:114
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:1563
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:273
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
Definition Function.cpp:309
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
Definition Function.cpp:172
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
Definition Function.cpp:297
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition Function.cpp:128
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.
Functions, function parameters, and return types can have attributes to indicate how they should be t...
Definition Attributes.h:69
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:88
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
Definition Attributes.h:101
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:482
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition BasicBlock.h:233
BinaryOps getOpcode() const
Definition InstrTypes.h:374
Conditional or Unconditional Branch instruction.
unsigned getNumSuccessors() const
static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i) const
Value * getCondition() const
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
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
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:372
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
Definition InstrTypes.h:610
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:617
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition InstrTypes.h:915
bool isFalseWhenEqual() const
This is just a convenience.
Definition InstrTypes.h:948
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:676
@ ICMP_NE
not equal
Definition InstrTypes.h:698
bool isTrueWhenEqual() const
This is just a convenience.
Definition InstrTypes.h:942
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:765
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:536
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.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:178
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:256
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:174
iterator end()
Definition DenseMap.h:81
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:169
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:241
Analysis pass which computes a DominatorTree.
Definition Dominators.h:283
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:164
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:807
Argument * arg_iterator
Definition Function.h:72
iterator_range< arg_iterator > args()
Definition Function.h:890
const Function & getFunction() const
Definition Function.h:164
size_t arg_size() const
Definition Function.h:899
Argument * getArg(unsigned i) const
Definition Function.h:884
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:730
CycleT * getCycle(const BlockT *Block) const
Find the innermost cycle containing a given 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:328
bool hasLocalLinkage() const
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:2039
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:527
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2788
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.
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.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
ConstantRange getConstantRange(Value *V, Instruction *CxtI, 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:1569
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
bool empty() const
Definition MapVector.h:77
static MemoryEffectsBase readOnly()
Definition ModRef.h:130
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:220
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:140
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:146
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
Definition ModRef.h:239
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:193
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
Definition ModRef.h:229
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:223
static MemoryEffectsBase writeOnly()
Definition ModRef.h:135
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:163
static MemoryEffectsBase none()
Definition ModRef.h:125
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
Definition ModRef.h:250
static MemoryEffectsBase unknown()
Definition ModRef.h:120
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 const SCEV * 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:151
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:183
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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:712
TypeSize getElementOffset(unsigned Idx) const
Definition DataLayout.h:743
TypeSize getElementOffsetInBits(unsigned Idx) const
Definition DataLayout.h:748
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:45
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:267
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:270
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:240
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:139
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:245
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:118
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:24
Value * getOperand(unsigned i) const
Definition User.h:232
unsigned getNumOperands() const
Definition User.h:254
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:256
static constexpr uint64_t MaximumAlignment
Definition Value.h:830
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:546
iterator_range< user_iterator > users()
Definition Value.h:426
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:346
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.cpp:1099
static constexpr unsigned MaxAlignmentExponent
The maximum alignment for instructions.
Definition Value.h:829
iterator_range< use_iterator > uses()
Definition Value.h:380
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
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.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
raw_ostream & operator<<(raw_ostream &OS, const RangeTy &R)
Definition Attributor.h:323
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 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.
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
Definition Attributor.h:166
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
Definition Attributor.h:182
@ Intraprocedural
Definition Attributor.h:183
@ Interprocedural
Definition Attributor.h:184
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.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
@ Unsupported
This operation is completely unsupported on the target.
@ Undef
Value of the register doesn't matter.
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:55
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:48
@ 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:60
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:708
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:667
constexpr double e
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
Context & getContext() const
Definition BasicBlock.h:99
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:532
@ Length
Definition DWP.cpp:532
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:362
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
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:1737
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:1667
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:365
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
Definition InstrProf.h:296
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:1545
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:301
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)
Definition STLExtras.h:364
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
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
CycleInfo::CycleT Cycle
Definition CycleInfo.h:24
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:1744
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:331
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveNullness)
{launder,strip}.invariant.group returns pointer that aliases its argument, and it only captures point...
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1634
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:207
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:359
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:421
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.
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.
LLVM_ABI RetainedKnowledge getKnowledgeFromUse(const Use *U, ArrayRef< Attribute::AttrKind > AttrKinds)
Return a valid Knowledge associated to the Use U if its Attribute kind is in AttrKinds.
@ 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.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
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)
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.
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:363
ChangeStatus
{
Definition Attributor.h:496
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:100
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:508
@ NONE
Do not track a dependence between source and target.
Definition Attributor.h:509
@ REQUIRED
The target cannot be valid if the source is not.
Definition Attributor.h:507
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:383
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:330
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool capturesNothing(CaptureComponents CC)
Definition ModRef.h:320
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
Definition Assumptions.h:29
constexpr bool isCallableCC(CallingConv::ID CC)
GenericCycleInfo< SSAContext > CycleInfo
Definition CycleInfo.h:23
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:872
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
See AbstractState::isAtFixpoint().
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
See AbstractState::indicateOptimisticFixpoint().
ChangeStatus indicatePessimisticFixpoint() override
See AbstractState::indicatePessimisticFixpoint().
static State getBestState(const State &SIS)
Return the best possible representable state.
bool isValidState() const override
See AbstractState::isValidState().
----------------—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-fp-math" and "denormal-fp-ma...
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)
See IRAttribute::isImpliedByIR.
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)
See IRAttribute::isImpliedByIR.
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.
static LLVM_ABI bool isNoSyncIntrinsic(const Instruction *I)
Helper function specific for intrinsics which are potentially volatile.
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)
See IRAttribute::isImpliedByIR.
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)
See AbstractAttribute::isImpliedByIR(...).
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:241
static constexpr int64_t Unknown
Definition Attributor.h:320
static RangeTy getUnknown()
Definition Attributor.h:247
Value * getValue() const
Definition Attributor.h:194
const Instruction * getCtxI() const
Definition Attributor.h:195
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.
Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign but the instruction.
static unsigned getHashValue(const Access &A)
static Access getTombstoneKey()
DenseMapInfo< Instruction * > Base
static bool isEqual(const Access &LHS, const Access &RHS)
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:77
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 DenormalMode getDefault()
Return the assumed default mode for a function without denormal-fp-math.
static constexpr DenormalMode getInvalid()
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 ReachabilityQueryInfo< ToTy > * getTombstoneKey()
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
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Definition Attributor.h:593
Function * getAssociatedFunction() const
Return the associated function, if any.
Definition Attributor.h:724
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
Definition Attributor.h:661
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
Definition Attributor.h:643
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:617
CallBase CallBaseContext
Definition Attributor.h:596
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
Definition Attributor.h:811
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
Definition Attributor.h:629
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
Definition Attributor.h:666
@ IRP_ARGUMENT
An attribute for a function argument.
Definition Attributor.h:607
@ IRP_RETURNED
An attribute for the function return value.
Definition Attributor.h:603
@ IRP_CALL_SITE
An attribute for a call site (function scope).
Definition Attributor.h:606
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
Definition Attributor.h:604
@ IRP_FUNCTION
An attribute for a function (scope).
Definition Attributor.h:605
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
Definition Attributor.h:608
@ IRP_INVALID
An invalid position.
Definition Attributor.h:600
Instruction * getCtxI() const
Return the context instruction, if any.
Definition Attributor.h:777
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Definition Attributor.h:650
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
Definition Attributor.h:800
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
Definition Attributor.h:636
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Definition Attributor.h:939
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Definition Attributor.h:791
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Definition Attributor.h:710
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:820
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:689
Kind getPositionKind() const
Return the associated position kind.
Definition Attributor.h:889
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
Definition Attributor.h:921
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Definition Attributor.h:656
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
Definition Attributor.h:765
Data structure to hold cached (LLVM-IR) information.
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
FPClassTest KnownFPClasses
Floating-point classes the value could be one of.
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
See AbstractAttribute::getState(...).
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.