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