LLVM 24.0.0git
AttributorAttributes.cpp
Go to the documentation of this file.
1//===- AttributorAttributes.cpp - Attributes for Attributor deduction -----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// See the Attributor.h file comment and the class descriptions in that file for
10// more information.
11//
12//===----------------------------------------------------------------------===//
13
15
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/MapVector.h"
22#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SetVector.h"
27#include "llvm/ADT/Statistic.h"
40#include "llvm/IR/Argument.h"
41#include "llvm/IR/Assumptions.h"
42#include "llvm/IR/Attributes.h"
43#include "llvm/IR/BasicBlock.h"
44#include "llvm/IR/Constant.h"
45#include "llvm/IR/Constants.h"
46#include "llvm/IR/DataLayout.h"
48#include "llvm/IR/GlobalValue.h"
49#include "llvm/IR/IRBuilder.h"
50#include "llvm/IR/InlineAsm.h"
51#include "llvm/IR/InstrTypes.h"
52#include "llvm/IR/Instruction.h"
55#include "llvm/IR/IntrinsicsAMDGPU.h"
56#include "llvm/IR/IntrinsicsNVPTX.h"
57#include "llvm/IR/LLVMContext.h"
58#include "llvm/IR/MDBuilder.h"
59#include "llvm/IR/NoFolder.h"
60#include "llvm/IR/Value.h"
61#include "llvm/IR/ValueHandle.h"
76#include <cassert>
77#include <numeric>
78#include <optional>
79#include <string>
80
81using namespace llvm;
82
83#define DEBUG_TYPE "attributor"
84
86 "attributor-manifest-internal", cl::Hidden,
87 cl::desc("Manifest Attributor internal string attributes."),
88 cl::init(false));
89
90static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
92
93template <>
95
97
99 "attributor-max-potential-values", cl::Hidden,
100 cl::desc("Maximum number of potential values to be "
101 "tracked for each position."),
103 cl::init(7));
104
106 "attributor-max-potential-values-iterations", cl::Hidden,
107 cl::desc(
108 "Maximum number of iterations we keep dismantling potential values."),
109 cl::init(64));
110
111STATISTIC(NumAAs, "Number of abstract attributes created");
112STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");
113
114// Some helper macros to deal with statistics tracking.
115//
116// Usage:
117// For simple IR attribute tracking overload trackStatistics in the abstract
118// attribute and choose the right STATS_DECLTRACK_********* macro,
119// e.g.,:
120// void trackStatistics() const override {
121// STATS_DECLTRACK_ARG_ATTR(returned)
122// }
123// If there is a single "increment" side one can use the macro
124// STATS_DECLTRACK with a custom message. If there are multiple increment
125// sides, STATS_DECL and STATS_TRACK can also be used separately.
126//
127#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME) \
128 ("Number of " #TYPE " marked '" #NAME "'")
129#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
130#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
131#define STATS_DECL(NAME, TYPE, MSG) \
132 STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
133#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
134#define STATS_DECLTRACK(NAME, TYPE, MSG) \
135 {STATS_DECL(NAME, TYPE, MSG) STATS_TRACK(NAME, TYPE)}
136#define STATS_DECLTRACK_ARG_ATTR(NAME) \
137 STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
138#define STATS_DECLTRACK_CSARG_ATTR(NAME) \
139 STATS_DECLTRACK(NAME, CSArguments, \
140 BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
141#define STATS_DECLTRACK_FN_ATTR(NAME) \
142 STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
143#define STATS_DECLTRACK_CS_ATTR(NAME) \
144 STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
145#define STATS_DECLTRACK_FNRET_ATTR(NAME) \
146 STATS_DECLTRACK(NAME, FunctionReturn, \
147 BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
148#define STATS_DECLTRACK_CSRET_ATTR(NAME) \
149 STATS_DECLTRACK(NAME, CSReturn, \
150 BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
151#define STATS_DECLTRACK_FLOATING_ATTR(NAME) \
152 STATS_DECLTRACK(NAME, Floating, \
153 ("Number of floating values known to be '" #NAME "'"))
154
155// Specialization of the operator<< for abstract attributes subclasses. This
156// disambiguates situations where multiple operators are applicable.
157namespace llvm {
158#define PIPE_OPERATOR(CLASS) \
159 raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) { \
160 return OS << static_cast<const AbstractAttribute &>(AA); \
161 }
162
202
203#undef PIPE_OPERATOR
204
205template <>
207 const DerefState &R) {
208 ChangeStatus CS0 =
209 clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
210 ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
211 return CS0 | CS1;
212}
213
214} // namespace llvm
215
216static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
217 bool HeaderOnly, CycleRef *CPtr = nullptr) {
218 if (!CI)
219 return true;
220 auto *BB = I->getParent();
221 CycleRef C = CI->getCycle(BB);
222 if (!C)
223 return false;
224 if (CPtr)
225 *CPtr = C;
226 return !HeaderOnly || BB == CI->getHeader(C);
227}
228
229/// Checks if a type could have padding bytes.
230static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
231 // There is no size information, so be conservative.
232 if (!Ty->isSized())
233 return false;
234
235 // If the alloc size is not equal to the storage size, then there are padding
236 // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
237 if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
238 return false;
239
240 // FIXME: This isn't the right way to check for padding in vectors with
241 // non-byte-size elements.
242 if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
243 return isDenselyPacked(SeqTy->getElementType(), DL);
244
245 // For array types, check for padding within members.
246 if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
247 return isDenselyPacked(SeqTy->getElementType(), DL);
248
249 if (!isa<StructType>(Ty))
250 return true;
251
252 // Check for padding within and between elements of a struct.
253 StructType *StructTy = cast<StructType>(Ty);
254 const StructLayout *Layout = DL.getStructLayout(StructTy);
255 uint64_t StartPos = 0;
256 for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
257 Type *ElTy = StructTy->getElementType(I);
258 if (!isDenselyPacked(ElTy, DL))
259 return false;
260 if (StartPos != Layout->getElementOffsetInBits(I))
261 return false;
262 StartPos += DL.getTypeAllocSizeInBits(ElTy);
263 }
264
265 return true;
266}
267
268/// Get pointer operand of memory accessing instruction. If \p I is
269/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
270/// is set to false and the instruction is volatile, return nullptr.
272 bool AllowVolatile) {
273 if (!AllowVolatile && I->isVolatile())
274 return nullptr;
275
276 if (auto *LI = dyn_cast<LoadInst>(I)) {
277 return LI->getPointerOperand();
278 }
279
280 if (auto *SI = dyn_cast<StoreInst>(I)) {
281 return SI->getPointerOperand();
282 }
283
284 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
285 return CXI->getPointerOperand();
286 }
287
288 if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
289 return RMWI->getPointerOperand();
290 }
291
292 return nullptr;
293}
294
295/// Helper function to create a pointer based on \p Ptr, and advanced by \p
296/// Offset bytes.
297static Value *constructPointer(Value *Ptr, int64_t Offset,
298 IRBuilder<NoFolder> &IRB) {
299 LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
300 << "-bytes\n");
301
302 if (Offset)
303 Ptr = IRB.CreatePtrAdd(Ptr, IRB.getInt64(Offset),
304 Ptr->getName() + ".b" + Twine(Offset));
305 return Ptr;
306}
307
308static const Value *
310 const Value *Val, const DataLayout &DL, APInt &Offset,
311 bool GetMinOffset, bool AllowNonInbounds,
312 bool UseAssumed = false) {
313
314 auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
315 const IRPosition &Pos = IRPosition::value(V);
316 // Only track dependence if we are going to use the assumed info.
317 const AAValueConstantRange *ValueConstantRangeAA =
318 A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
319 UseAssumed ? DepClassTy::OPTIONAL
321 if (!ValueConstantRangeAA)
322 return false;
323 ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()
324 : ValueConstantRangeAA->getKnown();
325 if (Range.isFullSet())
326 return false;
327
328 // We can only use the lower part of the range because the upper part can
329 // be higher than what the value can really be.
330 if (GetMinOffset)
331 ROffset = Range.getSignedMin();
332 else
333 ROffset = Range.getSignedMax();
334 return true;
335 };
336
337 return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
338 /* AllowInvariant */ true,
339 AttributorAnalysis);
340}
341
342static const Value *
344 const Value *Ptr, int64_t &BytesOffset,
345 const DataLayout &DL, bool AllowNonInbounds = false) {
346 APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
347 const Value *Base =
348 stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
349 /* GetMinOffset */ true, AllowNonInbounds);
350
351 BytesOffset = OffsetAPInt.getSExtValue();
352 return Base;
353}
354
355/// Clamp the information known for all returned values of a function
356/// (identified by \p QueryingAA) into \p S.
357template <typename AAType, typename StateType = typename AAType::StateType,
358 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
359 bool RecurseForSelectAndPHI = true>
361 Attributor &A, const AAType &QueryingAA, StateType &S,
362 const IRPosition::CallBaseContext *CBContext = nullptr) {
363 LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
364 << QueryingAA << " into " << S << "\n");
365
366 assert((QueryingAA.getIRPosition().getPositionKind() ==
368 QueryingAA.getIRPosition().getPositionKind() ==
370 "Can only clamp returned value states for a function returned or call "
371 "site returned position!");
372
373 // Use an optional state as there might not be any return values and we want
374 // to join (IntegerState::operator&) the state of all there are.
375 std::optional<StateType> T;
376
377 // Callback for each possibly returned value.
378 auto CheckReturnValue = [&](Value &RV) -> bool {
379 const IRPosition &RVPos = IRPosition::value(RV, CBContext);
380 // If possible, use the hasAssumedIRAttr interface.
381 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
382 bool IsKnown;
384 A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);
385 }
386
387 const AAType *AA =
388 A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
389 if (!AA)
390 return false;
391 LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
392 << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");
393 const StateType &AAS = AA->getState();
394 if (!T)
395 T = StateType::getBestState(AAS);
396 *T &= AAS;
397 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
398 << "\n");
399 return T->isValidState();
400 };
401
402 if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
404 RecurseForSelectAndPHI))
405 S.indicatePessimisticFixpoint();
406 else if (T)
407 S ^= *T;
408}
409
410namespace {
411/// Helper class for generic deduction: return value -> returned position.
412template <typename AAType, typename BaseType,
413 typename StateType = typename BaseType::StateType,
414 bool PropagateCallBaseContext = false,
415 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
416 bool RecurseForSelectAndPHI = true>
417struct AAReturnedFromReturnedValues : public BaseType {
418 AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
419 : BaseType(IRP, A) {}
420
421 /// See AbstractAttribute::updateImpl(...).
422 ChangeStatus updateImpl(Attributor &A) override {
423 StateType S(StateType::getBestState(this->getState()));
424 clampReturnedValueStates<AAType, StateType, IRAttributeKind,
425 RecurseForSelectAndPHI>(
426 A, *this, S,
427 PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
428 // TODO: If we know we visited all returned values, thus no are assumed
429 // dead, we can take the known information from the state T.
430 return clampStateAndIndicateChange<StateType>(this->getState(), S);
431 }
432};
433
434/// Clamp the information known at all call sites for a given argument
435/// (identified by \p QueryingAA) into \p S.
436template <typename AAType, typename StateType = typename AAType::StateType,
437 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
438static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
439 StateType &S) {
440 LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
441 << QueryingAA << " into " << S << "\n");
442
443 assert(QueryingAA.getIRPosition().getPositionKind() ==
445 "Can only clamp call site argument states for an argument position!");
446
447 // Use an optional state as there might not be any return values and we want
448 // to join (IntegerState::operator&) the state of all there are.
449 std::optional<StateType> T;
450
451 // The argument number which is also the call site argument number.
452 unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();
453
454 auto CallSiteCheck = [&](AbstractCallSite ACS) {
455 const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
456 // Check if a coresponding argument was found or if it is on not associated
457 // (which can happen for callback calls).
458 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
459 return false;
460
461 // If possible, use the hasAssumedIRAttr interface.
462 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
463 bool IsKnown;
465 A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);
466 }
467
468 const AAType *AA =
469 A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
470 if (!AA)
471 return false;
472 LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
473 << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos
474 << "\n");
475 const StateType &AAS = AA->getState();
476 if (!T)
477 T = StateType::getBestState(AAS);
478 *T &= AAS;
479 LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
480 << "\n");
481 return T->isValidState();
482 };
483
484 bool UsedAssumedInformation = false;
485 if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
486 UsedAssumedInformation))
487 S.indicatePessimisticFixpoint();
488 else if (T)
489 S ^= *T;
490}
491
492/// This function is the bridge between argument position and the call base
493/// context.
494template <typename AAType, typename BaseType,
495 typename StateType = typename AAType::StateType,
496 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
497bool getArgumentStateFromCallBaseContext(Attributor &A,
498 BaseType &QueryingAttribute,
499 IRPosition &Pos, StateType &State) {
501 "Expected an 'argument' position !");
502 const CallBase *CBContext = Pos.getCallBaseContext();
503 if (!CBContext)
504 return false;
505
506 int ArgNo = Pos.getCallSiteArgNo();
507 assert(ArgNo >= 0 && "Invalid Arg No!");
508 const IRPosition CBArgPos = IRPosition::callsite_argument(*CBContext, ArgNo);
509
510 // If possible, use the hasAssumedIRAttr interface.
511 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
512 bool IsKnown;
514 A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);
515 }
516
517 const auto *AA =
518 A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);
519 if (!AA)
520 return false;
521 const StateType &CBArgumentState =
522 static_cast<const StateType &>(AA->getState());
523
524 LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"
525 << "Position:" << Pos << "CB Arg state:" << CBArgumentState
526 << "\n");
527
528 // NOTE: If we want to do call site grouping it should happen here.
529 State ^= CBArgumentState;
530 return true;
531}
532
533/// Helper class for generic deduction: call site argument -> argument position.
534template <typename AAType, typename BaseType,
535 typename StateType = typename AAType::StateType,
536 bool BridgeCallBaseContext = false,
537 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
538struct AAArgumentFromCallSiteArguments : public BaseType {
539 AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
540 : BaseType(IRP, A) {}
541
542 /// See AbstractAttribute::updateImpl(...).
543 ChangeStatus updateImpl(Attributor &A) override {
544 StateType S = StateType::getBestState(this->getState());
545
546 if (BridgeCallBaseContext) {
547 bool Success =
548 getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,
549 IRAttributeKind>(
550 A, *this, this->getIRPosition(), S);
551 if (Success)
552 return clampStateAndIndicateChange<StateType>(this->getState(), S);
553 }
554 clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,
555 S);
556
557 // TODO: If we know we visited all incoming values, thus no are assumed
558 // dead, we can take the known information from the state T.
559 return clampStateAndIndicateChange<StateType>(this->getState(), S);
560 }
561};
562
563/// Helper class for generic replication: function returned -> cs returned.
564template <typename AAType, typename BaseType,
565 typename StateType = typename BaseType::StateType,
566 bool IntroduceCallBaseContext = false,
567 Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
568struct AACalleeToCallSite : public BaseType {
569 AACalleeToCallSite(const IRPosition &IRP, Attributor &A) : BaseType(IRP, A) {}
570
571 /// See AbstractAttribute::updateImpl(...).
572 ChangeStatus updateImpl(Attributor &A) override {
573 auto IRPKind = this->getIRPosition().getPositionKind();
575 IRPKind == IRPosition::IRP_CALL_SITE) &&
576 "Can only wrap function returned positions for call site "
577 "returned positions!");
578 auto &S = this->getState();
579
580 CallBase &CB = cast<CallBase>(this->getAnchorValue());
581 if (IntroduceCallBaseContext)
582 LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:" << CB
583 << "\n");
584
585 ChangeStatus Changed = ChangeStatus::UNCHANGED;
586 auto CalleePred = [&](ArrayRef<const Function *> Callees) {
587 for (const Function *Callee : Callees) {
588 IRPosition FnPos =
590 ? IRPosition::returned(*Callee,
591 IntroduceCallBaseContext ? &CB : nullptr)
592 : IRPosition::function(
593 *Callee, IntroduceCallBaseContext ? &CB : nullptr);
594 // If possible, use the hasAssumedIRAttr interface.
595 if (Attribute::isEnumAttrKind(IRAttributeKind)) {
596 bool IsKnown;
598 A, this, FnPos, DepClassTy::REQUIRED, IsKnown))
599 return false;
600 continue;
601 }
602
603 const AAType *AA =
604 A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
605 if (!AA)
606 return false;
607 Changed |= clampStateAndIndicateChange(S, AA->getState());
608 if (S.isAtFixpoint())
609 return S.isValidState();
610 }
611 return true;
612 };
613 if (!A.checkForAllCallees(CalleePred, *this, CB))
614 return S.indicatePessimisticFixpoint();
615 return Changed;
616 }
617};
618
619/// Helper function to accumulate uses.
620template <class AAType, typename StateType = typename AAType::StateType>
621static void followUsesInContext(AAType &AA, Attributor &A,
623 const Instruction *CtxI,
625 StateType &State) {
626 auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
627 for (unsigned u = 0; u < Uses.size(); ++u) {
628 const Use *U = Uses[u];
629 if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
630 bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
631 if (Found && AA.followUseInMBEC(A, U, UserI, State))
632 Uses.insert_range(llvm::make_pointer_range(UserI->uses()));
633 }
634 }
635}
636
637/// Use the must-be-executed-context around \p I to add information into \p S.
638/// The AAType class is required to have `followUseInMBEC` method with the
639/// following signature and behaviour:
640///
641/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
642/// U - Underlying use.
643/// I - The user of the \p U.
644/// Returns true if the value should be tracked transitively.
645///
646template <class AAType, typename StateType = typename AAType::StateType>
647static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
648 Instruction &CtxI) {
649 const Value &Val = AA.getIRPosition().getAssociatedValue();
650 if (isa<ConstantData>(Val))
651 return;
652
654 A.getInfoCache().getMustBeExecutedContextExplorer();
655 if (!Explorer)
656 return;
657
658 // Container for (transitive) uses of the associated value.
660 for (const Use &U : Val.uses())
661 Uses.insert(&U);
662
663 followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);
664
665 if (S.isAtFixpoint())
666 return;
667
669 auto Pred = [&](const Instruction *I) {
670 if (const CondBrInst *Br = dyn_cast<CondBrInst>(I))
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 CondBrInst *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 unsigned getHashValue(const Access &A);
750 static bool isEqual(const Access &LHS, const Access &RHS);
751};
752
753/// Helper that allows RangeTy as a key in a DenseMap.
754template <> struct DenseMapInfo<AA::RangeTy> {
760
761 static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
762 return A == B;
763 }
764};
765
766} // namespace llvm
767
768/// A type to track pointer/struct usage and accesses for AAPointerInfo.
770 /// Return the best possible representable state.
771 static State getBestState(const State &SIS) { return State(); }
772
773 /// Return the worst possible representable state.
774 static State getWorstState(const State &SIS) {
775 State R;
776 R.indicatePessimisticFixpoint();
777 return R;
778 }
779
780 State() = default;
781 State(State &&SIS) = default;
782
783 const State &getAssumed() const { return *this; }
784
785 /// See AbstractState::isValidState().
786 bool isValidState() const override { return BS.isValidState(); }
787
788 /// See AbstractState::isAtFixpoint().
789 bool isAtFixpoint() const override { return BS.isAtFixpoint(); }
790
791 /// See AbstractState::indicateOptimisticFixpoint().
793 BS.indicateOptimisticFixpoint();
795 }
796
797 /// See AbstractState::indicatePessimisticFixpoint().
799 BS.indicatePessimisticFixpoint();
801 }
802
803 State &operator=(const State &R) {
804 if (this == &R)
805 return *this;
806 BS = R.BS;
807 AccessList = R.AccessList;
808 OffsetBins = R.OffsetBins;
809 RemoteIMap = R.RemoteIMap;
810 ReturnedOffsets = R.ReturnedOffsets;
811 return *this;
812 }
813
815 if (this == &R)
816 return *this;
817 std::swap(BS, R.BS);
818 std::swap(AccessList, R.AccessList);
819 std::swap(OffsetBins, R.OffsetBins);
820 std::swap(RemoteIMap, R.RemoteIMap);
821 std::swap(ReturnedOffsets, R.ReturnedOffsets);
822 return *this;
823 }
824
825 /// Add a new Access to the state at offset \p Offset and with size \p Size.
826 /// The access is associated with \p I, writes \p Content (if anything), and
827 /// is of kind \p Kind. If an Access already exists for the same \p I and same
828 /// \p RemoteI, the two are combined, potentially losing information about
829 /// offset and size. The resulting access must now be moved from its original
830 /// OffsetBin to the bin for its new offset.
831 ///
832 /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
834 Instruction &I, std::optional<Value *> Content,
836 Instruction *RemoteI = nullptr);
837
840 int64_t numOffsetBins() const { return OffsetBins.size(); }
841
842 const AAPointerInfo::Access &getAccess(unsigned Index) const {
843 return AccessList[Index];
844 }
845
846protected:
847 // Every memory instruction results in an Access object. We maintain a list of
848 // all Access objects that we own, along with the following maps:
849 //
850 // - OffsetBins: RangeTy -> { Access }
851 // - RemoteIMap: RemoteI x LocalI -> Access
852 //
853 // A RemoteI is any instruction that accesses memory. RemoteI is different
854 // from LocalI if and only if LocalI is a call; then RemoteI is some
855 // instruction in the callgraph starting from LocalI. Multiple paths in the
856 // callgraph from LocalI to RemoteI may produce multiple accesses, but these
857 // are all combined into a single Access object. This may result in loss of
858 // information in RangeTy in the Access object.
862
863 /// Flag to determine if the underlying pointer is reaching a return statement
864 /// in the associated function or not. Returns in other functions cause
865 /// invalidation.
867
868 /// See AAPointerInfo::forallInterferingAccesses.
869 template <typename F>
871 if (!isValidState() || !ReturnedOffsets.isUnassigned())
872 return false;
873
874 for (const auto &It : OffsetBins) {
875 AA::RangeTy ItRange = It.getFirst();
876 if (!Range.mayOverlap(ItRange))
877 continue;
878 bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
879 for (auto Index : It.getSecond()) {
880 auto &Access = AccessList[Index];
881 if (!CB(Access, IsExact))
882 return false;
883 }
884 }
885 return true;
886 }
887
888 /// See AAPointerInfo::forallInterferingAccesses.
889 template <typename F>
891 AA::RangeTy &Range) const {
892 if (!isValidState() || !ReturnedOffsets.isUnassigned())
893 return false;
894
895 auto LocalList = RemoteIMap.find(&I);
896 if (LocalList == RemoteIMap.end()) {
897 return true;
898 }
899
900 for (unsigned Index : LocalList->getSecond()) {
901 for (auto &R : AccessList[Index]) {
902 Range &= R;
903 if (Range.offsetAndSizeAreUnknown())
904 break;
905 }
906 }
908 }
909
910private:
911 /// State to track fixpoint and validity.
912 BooleanState BS;
913};
914
917 std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
918 Instruction *RemoteI) {
919 RemoteI = RemoteI ? RemoteI : &I;
920
921 // Check if we have an access for this instruction, if not, simply add it.
922 auto &LocalList = RemoteIMap[RemoteI];
923 bool AccExists = false;
924 unsigned AccIndex = AccessList.size();
925 for (auto Index : LocalList) {
926 auto &A = AccessList[Index];
927 if (A.getLocalInst() == &I) {
928 AccExists = true;
929 AccIndex = Index;
930 break;
931 }
932 }
933
934 auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
935 LLVM_DEBUG(if (ToAdd.size()) dbgs()
936 << "[AAPointerInfo] Inserting access in new offset bins\n";);
937
938 for (auto Key : ToAdd) {
939 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
940 OffsetBins[Key].insert(AccIndex);
941 }
942 };
943
944 if (!AccExists) {
945 AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
946 assert((AccessList.size() == AccIndex + 1) &&
947 "New Access should have been at AccIndex");
948 LocalList.push_back(AccIndex);
949 AddToBins(AccessList[AccIndex].getRanges());
951 }
952
953 // Combine the new Access with the existing Access, and then update the
954 // mapping in the offset bins.
955 AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
956 auto &Current = AccessList[AccIndex];
957 auto Before = Current;
958 Current &= Acc;
959 if (Current == Before)
961
962 auto &ExistingRanges = Before.getRanges();
963 auto &NewRanges = Current.getRanges();
964
965 // Ranges that are in the old access but not the new access need to be removed
966 // from the offset bins.
968 AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
969 LLVM_DEBUG(if (ToRemove.size()) dbgs()
970 << "[AAPointerInfo] Removing access from old offset bins\n";);
971
972 for (auto Key : ToRemove) {
973 LLVM_DEBUG(dbgs() << " key " << Key << "\n");
974 assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
975 auto &Bin = OffsetBins[Key];
976 assert(Bin.count(AccIndex) &&
977 "Expected bin to actually contain the Access.");
978 Bin.erase(AccIndex);
979 }
980
981 // Ranges that are in the new access but not the old access need to be added
982 // to the offset bins.
984 AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
985 AddToBins(ToAdd);
987}
988
989namespace {
990
991#ifndef NDEBUG
993 const AAPointerInfo::OffsetInfo &OI) {
994 OS << llvm::interleaved_array(OI);
995 return OS;
996}
997#endif // NDEBUG
998
999struct AAPointerInfoImpl
1000 : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
1002 AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
1003
1004 /// See AbstractAttribute::getAsStr().
1005 const std::string getAsStr(Attributor *A) const override {
1006 return std::string("PointerInfo ") +
1007 (isValidState() ? (std::string("#") +
1008 std::to_string(OffsetBins.size()) + " bins")
1009 : "<invalid>") +
1010 (reachesReturn()
1011 ? (" (returned:" +
1012 join(map_range(ReturnedOffsets,
1013 [](int64_t O) { return std::to_string(O); }),
1014 ", ") +
1015 ")")
1016 : "");
1017 }
1018
1019 /// See AbstractAttribute::manifest(...).
1020 ChangeStatus manifest(Attributor &A) override {
1021 return AAPointerInfo::manifest(A);
1022 }
1023
1024 const_bin_iterator begin() const override { return State::begin(); }
1025 const_bin_iterator end() const override { return State::end(); }
1026 int64_t numOffsetBins() const override { return State::numOffsetBins(); }
1027 bool reachesReturn() const override {
1028 return !ReturnedOffsets.isUnassigned();
1029 }
1030 void addReturnedOffsetsTo(OffsetInfo &OI) const override {
1031 if (ReturnedOffsets.isUnknown()) {
1032 OI.setUnknown();
1033 return;
1034 }
1035
1036 OffsetInfo MergedOI;
1037 for (auto Offset : ReturnedOffsets) {
1038 OffsetInfo TmpOI = OI;
1039 TmpOI.addToAll(Offset);
1040 MergedOI.merge(TmpOI);
1041 }
1042 OI = std::move(MergedOI);
1043 }
1044
1045 ChangeStatus setReachesReturn(const OffsetInfo &ReachedReturnedOffsets) {
1046 if (ReturnedOffsets.isUnknown())
1047 return ChangeStatus::UNCHANGED;
1048 if (ReachedReturnedOffsets.isUnknown()) {
1049 ReturnedOffsets.setUnknown();
1050 return ChangeStatus::CHANGED;
1051 }
1052 if (ReturnedOffsets.merge(ReachedReturnedOffsets))
1053 return ChangeStatus::CHANGED;
1054 return ChangeStatus::UNCHANGED;
1055 }
1056
1057 bool forallInterferingAccesses(
1058 AA::RangeTy Range,
1059 function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
1060 const override {
1061 return State::forallInterferingAccesses(Range, CB);
1062 }
1063
1064 bool forallInterferingAccesses(
1065 Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
1066 bool FindInterferingWrites, bool FindInterferingReads,
1067 function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
1068 AA::RangeTy &Range,
1069 function_ref<bool(const Access &)> SkipCB) const override {
1070 HasBeenWrittenTo = false;
1071
1072 SmallPtrSet<const Access *, 8> DominatingWrites;
1073 SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;
1074
1075 Function &Scope = *I.getFunction();
1076 bool IsKnownNoSync;
1077 bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(
1078 A, &QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1079 IsKnownNoSync);
1080 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
1081 IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
1082 bool AllInSameNoSyncFn = IsAssumedNoSync;
1083 bool InstIsExecutedByInitialThreadOnly =
1084 ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);
1085
1086 // If the function is not ending in aligned barriers, we need the stores to
1087 // be in aligned barriers. The load being in one is not sufficient since the
1088 // store might be executed by a thread that disappears after, causing the
1089 // aligned barrier guarding the load to unblock and the load to read a value
1090 // that has no CFG path to the load.
1091 bool InstIsExecutedInAlignedRegion =
1092 FindInterferingReads && ExecDomainAA &&
1093 ExecDomainAA->isExecutedInAlignedRegion(A, I);
1094
1095 if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
1096 A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1097
1098 InformationCache &InfoCache = A.getInfoCache();
1099 bool IsThreadLocalObj =
1100 AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);
1101
1102 // Helper to determine if we need to consider threading, which we cannot
1103 // right now. However, if the function is (assumed) nosync or the thread
1104 // executing all instructions is the main thread only we can ignore
1105 // threading. Also, thread-local objects do not require threading reasoning.
1106 // Finally, we can ignore threading if either access is executed in an
1107 // aligned region.
1108 auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
1109 if (IsThreadLocalObj || AllInSameNoSyncFn)
1110 return true;
1111 const auto *FnExecDomainAA =
1112 I.getFunction() == &Scope
1113 ? ExecDomainAA
1114 : A.lookupAAFor<AAExecutionDomain>(
1115 IRPosition::function(*I.getFunction()), &QueryingAA,
1116 DepClassTy::NONE);
1117 if (!FnExecDomainAA)
1118 return false;
1119 if (InstIsExecutedInAlignedRegion ||
1120 (FindInterferingWrites &&
1121 FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {
1122 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1123 return true;
1124 }
1125 if (InstIsExecutedByInitialThreadOnly &&
1126 FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
1127 A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
1128 return true;
1129 }
1130 return false;
1131 };
1132
1133 // Helper to determine if the access is executed by the same thread as the
1134 // given instruction, for now it is sufficient to avoid any potential
1135 // threading effects as we cannot deal with them anyway.
1136 auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
1137 return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
1138 (Acc.getRemoteInst() != Acc.getLocalInst() &&
1139 CanIgnoreThreadingForInst(*Acc.getLocalInst()));
1140 };
1141
1142 // TODO: Use inter-procedural reachability and dominance.
1143 bool IsKnownNoRecurse;
1145 A, this, IRPosition::function(Scope), DepClassTy::OPTIONAL,
1146 IsKnownNoRecurse);
1147
1148 // TODO: Use reaching kernels from AAKernelInfo (or move it to
1149 // AAExecutionDomain) such that we allow scopes other than kernels as long
1150 // as the reaching kernels are disjoint.
1151 bool InstInKernel = A.getInfoCache().isKernel(Scope);
1152 bool ObjHasKernelLifetime = false;
1153 const bool UseDominanceReasoning =
1154 FindInterferingWrites && IsKnownNoRecurse;
1155 const DominatorTree *DT =
1156 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);
1157
1158 // Helper to check if a value has "kernel lifetime", that is it will not
1159 // outlive a GPU kernel. This is true for shared, constant, and local
1160 // globals on AMD and NVIDIA GPUs.
1161 auto HasKernelLifetime = [&](Value *V, Module &M) {
1162 if (!AA::isGPU(M))
1163 return false;
1164 unsigned VAS = V->getType()->getPointerAddressSpace();
1165 return AA::isGPUSharedAddressSpace(M, VAS) ||
1168 };
1169
1170 // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
1171 // to determine if we should look at reachability from the callee. For
1172 // certain pointers we know the lifetime and we do not have to step into the
1173 // callee to determine reachability as the pointer would be dead in the
1174 // callee. See the conditional initialization below.
1175 std::function<bool(const Function &)> IsLiveInCalleeCB;
1176
1177 if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
1178 // If the alloca containing function is not recursive the alloca
1179 // must be dead in the callee.
1180 const Function *AIFn = AI->getFunction();
1181 ObjHasKernelLifetime = A.getInfoCache().isKernel(*AIFn);
1182 bool IsKnownNoRecurse;
1184 A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL,
1185 IsKnownNoRecurse)) {
1186 IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
1187 }
1188 } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
1189 // If the global has kernel lifetime we can stop if we reach a kernel
1190 // as it is "dead" in the (unknown) callees.
1191 ObjHasKernelLifetime = HasKernelLifetime(GV, *GV->getParent());
1192 if (ObjHasKernelLifetime)
1193 IsLiveInCalleeCB = [&A](const Function &Fn) {
1194 return !A.getInfoCache().isKernel(Fn);
1195 };
1196 }
1197
1198 // Set of accesses/instructions that will overwrite the result and are
1199 // therefore blockers in the reachability traversal.
1200 AA::InstExclusionSetTy ExclusionSet;
1201
1202 auto AccessCB = [&](const Access &Acc, bool Exact) {
1203 Function *AccScope = Acc.getRemoteInst()->getFunction();
1204 bool AccInSameScope = AccScope == &Scope;
1205
1206 // If the object has kernel lifetime we can ignore accesses only reachable
1207 // by other kernels. For now we only skip accesses *in* other kernels.
1208 if (InstInKernel && ObjHasKernelLifetime && !AccInSameScope &&
1209 A.getInfoCache().isKernel(*AccScope))
1210 return true;
1211
1212 if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
1213 if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
1214 ExclusionSet.insert(Acc.getRemoteInst());
1215 }
1216
1217 if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
1218 (!FindInterferingReads || !Acc.isRead()))
1219 return true;
1220
1221 bool Dominates = FindInterferingWrites && DT && Exact &&
1222 Acc.isMustAccess() && AccInSameScope &&
1223 DT->dominates(Acc.getRemoteInst(), &I);
1224 if (Dominates)
1225 DominatingWrites.insert(&Acc);
1226
1227 // Track if all interesting accesses are in the same `nosync` function as
1228 // the given instruction.
1229 AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;
1230
1231 InterferingAccesses.push_back({&Acc, Exact});
1232 return true;
1233 };
1234 if (!State::forallInterferingAccesses(I, AccessCB, Range))
1235 return false;
1236
1237 HasBeenWrittenTo = !DominatingWrites.empty();
1238
1239 // Dominating writes form a chain, find the least/lowest member.
1240 Instruction *LeastDominatingWriteInst = nullptr;
1241 for (const Access *Acc : DominatingWrites) {
1242 if (!LeastDominatingWriteInst) {
1243 LeastDominatingWriteInst = Acc->getRemoteInst();
1244 } else if (DT->dominates(LeastDominatingWriteInst,
1245 Acc->getRemoteInst())) {
1246 LeastDominatingWriteInst = Acc->getRemoteInst();
1247 }
1248 }
1249
1250 // Helper to determine if we can skip a specific write access.
1251 auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
1252 if (SkipCB && SkipCB(Acc))
1253 return true;
1254 if (!CanIgnoreThreading(Acc))
1255 return false;
1256
1257 // Check read (RAW) dependences and write (WAR) dependences as necessary.
1258 // If we successfully excluded all effects we are interested in, the
1259 // access can be skipped.
1260 bool ReadChecked = !FindInterferingReads;
1261 bool WriteChecked = !FindInterferingWrites;
1262
1263 // If the instruction cannot reach the access, the former does not
1264 // interfere with what the access reads.
1265 if (!ReadChecked) {
1266 if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
1267 &ExclusionSet, IsLiveInCalleeCB))
1268 ReadChecked = true;
1269 }
1270 // If the instruction cannot be reach from the access, the latter does not
1271 // interfere with what the instruction reads.
1272 if (!WriteChecked) {
1273 if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
1274 &ExclusionSet, IsLiveInCalleeCB))
1275 WriteChecked = true;
1276 }
1277
1278 // If we still might be affected by the write of the access but there are
1279 // dominating writes in the function of the instruction
1280 // (HasBeenWrittenTo), we can try to reason that the access is overwritten
1281 // by them. This would have happend above if they are all in the same
1282 // function, so we only check the inter-procedural case. Effectively, we
1283 // want to show that there is no call after the dominting write that might
1284 // reach the access, and when it returns reach the instruction with the
1285 // updated value. To this end, we iterate all call sites, check if they
1286 // might reach the instruction without going through another access
1287 // (ExclusionSet) and at the same time might reach the access. However,
1288 // that is all part of AAInterFnReachability.
1289 if (!WriteChecked && HasBeenWrittenTo &&
1290 Acc.getRemoteInst()->getFunction() != &Scope) {
1291
1292 const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
1293 QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);
1294 if (FnReachabilityAA) {
1295 // Without going backwards in the call tree, can we reach the access
1296 // from the least dominating write. Do not allow to pass the
1297 // instruction itself either.
1298 bool Inserted = ExclusionSet.insert(&I).second;
1299
1300 if (!FnReachabilityAA->instructionCanReach(
1301 A, *LeastDominatingWriteInst,
1302 *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
1303 WriteChecked = true;
1304
1305 if (Inserted)
1306 ExclusionSet.erase(&I);
1307 }
1308 }
1309
1310 if (ReadChecked && WriteChecked)
1311 return true;
1312
1313 if (!DT || !UseDominanceReasoning)
1314 return false;
1315 if (!DominatingWrites.count(&Acc))
1316 return false;
1317 return LeastDominatingWriteInst != Acc.getRemoteInst();
1318 };
1319
1320 // Run the user callback on all accesses we cannot skip and return if
1321 // that succeeded for all or not.
1322 for (auto &It : InterferingAccesses) {
1323 if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
1324 !CanSkipAccess(*It.first, It.second)) {
1325 if (!UserCB(*It.first, It.second))
1326 return false;
1327 }
1328 }
1329 return true;
1330 }
1331
1332 ChangeStatus translateAndAddStateFromCallee(Attributor &A,
1333 const AAPointerInfo &OtherAA,
1334 CallBase &CB) {
1335 using namespace AA::PointerInfo;
1336 if (!OtherAA.getState().isValidState() || !isValidState())
1337 return indicatePessimisticFixpoint();
1338
1339 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1340 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1341 bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();
1342 Changed |= setReachesReturn(OtherAAImpl.ReturnedOffsets);
1343
1344 // Combine the accesses bin by bin.
1345 const auto &State = OtherAAImpl.getState();
1346 for (const auto &It : State) {
1347 for (auto Index : It.getSecond()) {
1348 const auto &RAcc = State.getAccess(Index);
1349 if (IsByval && !RAcc.isRead())
1350 continue;
1351 bool UsedAssumedInformation = false;
1352 AccessKind AK = RAcc.getKind();
1353 auto Content = A.translateArgumentToCallSiteContent(
1354 RAcc.getContent(), CB, *this, UsedAssumedInformation);
1355 AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
1356 AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));
1357
1358 Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
1359 RAcc.getType(), RAcc.getRemoteInst());
1360 }
1361 }
1362 return Changed;
1363 }
1364
1365 ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
1366 const OffsetInfo &Offsets, CallBase &CB,
1367 bool IsMustAcc) {
1368 using namespace AA::PointerInfo;
1369 if (!OtherAA.getState().isValidState() || !isValidState())
1370 return indicatePessimisticFixpoint();
1371
1372 const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
1373
1374 // Combine the accesses bin by bin.
1375 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1376 const auto &State = OtherAAImpl.getState();
1377 for (const auto &It : State) {
1378 for (auto Index : It.getSecond()) {
1379 const auto &RAcc = State.getAccess(Index);
1380 if (!IsMustAcc && RAcc.isAssumption())
1381 continue;
1382 for (auto Offset : Offsets) {
1383 auto NewRanges = Offset == AA::RangeTy::Unknown
1385 : RAcc.getRanges();
1386 if (!NewRanges.isUnknown()) {
1387 NewRanges.addToAllOffsets(Offset);
1388 }
1389 AccessKind AK = RAcc.getKind();
1390 if (!IsMustAcc)
1391 AK = AccessKind((AK & ~AK_MUST) | AK_MAY);
1392 Changed |= addAccess(A, NewRanges, CB, RAcc.getContent(), AK,
1393 RAcc.getType(), RAcc.getRemoteInst());
1394 }
1395 }
1396 }
1397 return Changed;
1398 }
1399
1400 /// Statistic tracking for all AAPointerInfo implementations.
1401 /// See AbstractAttribute::trackStatistics().
1402 void trackPointerInfoStatistics(const IRPosition &IRP) const {}
1403
1404 /// Dump the state into \p O.
1405 void dumpState(raw_ostream &O) {
1406 for (auto &It : OffsetBins) {
1407 O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
1408 << "] : " << It.getSecond().size() << "\n";
1409 for (auto AccIndex : It.getSecond()) {
1410 auto &Acc = AccessList[AccIndex];
1411 O << " - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
1412 if (Acc.getLocalInst() != Acc.getRemoteInst())
1413 O << " --> " << *Acc.getRemoteInst()
1414 << "\n";
1415 if (!Acc.isWrittenValueYetUndetermined()) {
1416 if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
1417 O << " - c: func " << Acc.getWrittenValue()->getName()
1418 << "\n";
1419 else if (Acc.getWrittenValue())
1420 O << " - c: " << *Acc.getWrittenValue() << "\n";
1421 else
1422 O << " - c: <unknown>\n";
1423 }
1424 }
1425 }
1426 }
1427};
1428
1429struct AAPointerInfoFloating : public AAPointerInfoImpl {
1431 AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
1432 : AAPointerInfoImpl(IRP, A) {}
1433
1434 /// Deal with an access and signal if it was handled successfully.
1435 bool handleAccess(Attributor &A, Instruction &I,
1436 std::optional<Value *> Content, AccessKind Kind,
1437 OffsetInfo::VecTy &Offsets, ChangeStatus &Changed,
1438 Type &Ty) {
1439 using namespace AA::PointerInfo;
1441 const DataLayout &DL = A.getDataLayout();
1442 TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
1443 if (!AccessSize.isScalable())
1444 Size = AccessSize.getFixedValue();
1445
1446 // Make a strictly ascending list of offsets as required by addAccess()
1447 SmallVector<int64_t> OffsetsSorted(Offsets.begin(), Offsets.end());
1448 llvm::sort(OffsetsSorted);
1449
1451 if (!VT || VT->getElementCount().isScalable() ||
1452 !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
1453 (*Content)->getType() != VT ||
1454 DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
1455 Changed =
1456 Changed | addAccess(A, {OffsetsSorted, Size}, I, Content, Kind, &Ty);
1457 } else {
1458 // Handle vector stores with constant content element-wise.
1459 // TODO: We could look for the elements or create instructions
1460 // representing them.
1461 // TODO: We need to push the Content into the range abstraction
1462 // (AA::RangeTy) to allow different content values for different
1463 // ranges. ranges. Hence, support vectors storing different values.
1464 Type *ElementType = VT->getElementType();
1465 int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
1466 auto *ConstContent = cast<Constant>(*Content);
1467 Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
1468 SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());
1469
1470 for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
1471 Value *ElementContent = ConstantExpr::getExtractElement(
1472 ConstContent, ConstantInt::get(Int32Ty, i));
1473
1474 // Add the element access.
1475 Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
1476 ElementContent, Kind, ElementType);
1477
1478 // Advance the offsets for the next element.
1479 for (auto &ElementOffset : ElementOffsets)
1480 ElementOffset += ElementSize;
1481 }
1482 }
1483 return true;
1484 };
1485
1486 /// See AbstractAttribute::updateImpl(...).
1487 ChangeStatus updateImpl(Attributor &A) override;
1488
1489 /// If the indices to \p GEP can be traced to constants, incorporate all
1490 /// of these into \p UsrOI.
1491 ///
1492 /// \return true iff \p UsrOI is updated.
1493 bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
1494 OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
1495 const GEPOperator *GEP);
1496
1497 /// See AbstractAttribute::trackStatistics()
1498 void trackStatistics() const override {
1499 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1500 }
1501};
1502
1503bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
1504 const DataLayout &DL,
1505 OffsetInfo &UsrOI,
1506 const OffsetInfo &PtrOI,
1507 const GEPOperator *GEP) {
1508 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
1509 SmallMapVector<Value *, APInt, 4> VariableOffsets;
1510 APInt ConstantOffset(BitWidth, 0);
1511
1512 assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
1513 "Don't look for constant values if the offset has already been "
1514 "determined to be unknown.");
1515
1516 if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
1517 UsrOI.setUnknown();
1518 return true;
1519 }
1520
1521 LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
1522 << (VariableOffsets.empty() ? "" : "not") << " constant "
1523 << *GEP << "\n");
1524
1525 auto Union = PtrOI;
1526 Union.addToAll(ConstantOffset.getSExtValue());
1527
1528 // Each VI in VariableOffsets has a set of potential constant values. Every
1529 // combination of elements, picked one each from these sets, is separately
1530 // added to the original set of offsets, thus resulting in more offsets.
1531 for (const auto &VI : VariableOffsets) {
1532 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
1533 *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
1534 if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
1535 UsrOI.setUnknown();
1536 return true;
1537 }
1538
1539 // UndefValue is treated as a zero, which leaves Union as is.
1540 if (PotentialConstantsAA->undefIsContained())
1541 continue;
1542
1543 // We need at least one constant in every set to compute an actual offset.
1544 // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
1545 // don't actually exist. In other words, the absence of constant values
1546 // implies that the operation can be assumed dead for now.
1547 auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
1548 if (AssumedSet.empty())
1549 return false;
1550
1551 OffsetInfo Product;
1552 for (const auto &ConstOffset : AssumedSet) {
1553 auto CopyPerOffset = Union;
1554 CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
1555 VI.second.getZExtValue());
1556 Product.merge(CopyPerOffset);
1557 }
1558 Union = Product;
1559 }
1560
1561 UsrOI = std::move(Union);
1562 return true;
1563}
1564
1565ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
1566 using namespace AA::PointerInfo;
1568 const DataLayout &DL = A.getDataLayout();
1569 Value &AssociatedValue = getAssociatedValue();
1570
1571 DenseMap<Value *, OffsetInfo> OffsetInfoMap;
1572 OffsetInfoMap[&AssociatedValue].insert(0);
1573
1574 auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
1575 // One does not simply walk into a map and assign a reference to a possibly
1576 // new location. That can cause an invalidation before the assignment
1577 // happens, like so:
1578 //
1579 // OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
1580 //
1581 // The RHS is a reference that may be invalidated by an insertion caused by
1582 // the LHS. So we ensure that the side-effect of the LHS happens first.
1583
1584 assert(OffsetInfoMap.contains(CurPtr) &&
1585 "CurPtr does not exist in the map!");
1586
1587 auto &UsrOI = OffsetInfoMap[Usr];
1588 auto &PtrOI = OffsetInfoMap[CurPtr];
1589 assert(!PtrOI.isUnassigned() &&
1590 "Cannot pass through if the input Ptr was not visited!");
1591 UsrOI.merge(PtrOI);
1592 Follow = true;
1593 return true;
1594 };
1595
1596 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
1597 Value *CurPtr = U.get();
1598 User *Usr = U.getUser();
1599 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
1600 << "\n");
1601 assert(OffsetInfoMap.count(CurPtr) &&
1602 "The current pointer offset should have been seeded!");
1603 assert(!OffsetInfoMap[CurPtr].isUnassigned() &&
1604 "Current pointer should be assigned");
1605
1606 if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
1607 if (CE->isCast())
1608 return HandlePassthroughUser(Usr, CurPtr, Follow);
1609 if (!isa<GEPOperator>(CE)) {
1610 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE
1611 << "\n");
1612 return false;
1613 }
1614 }
1615 if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
1616 // Note the order here, the Usr access might change the map, CurPtr is
1617 // already in it though.
1618 auto &UsrOI = OffsetInfoMap[Usr];
1619 auto &PtrOI = OffsetInfoMap[CurPtr];
1620
1621 if (UsrOI.isUnknown())
1622 return true;
1623
1624 if (PtrOI.isUnknown()) {
1625 Follow = true;
1626 UsrOI.setUnknown();
1627 return true;
1628 }
1629
1630 Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
1631 return true;
1632 }
1633 if (isa<PtrToIntInst>(Usr))
1634 return false;
1635 if (isa<CastInst>(Usr) || isa<SelectInst>(Usr))
1636 return HandlePassthroughUser(Usr, CurPtr, Follow);
1637 // Returns are allowed if they are in the associated functions. Users can
1638 // then check the call site return. Returns from other functions can't be
1639 // tracked and are cause for invalidation.
1640 if (auto *RI = dyn_cast<ReturnInst>(Usr)) {
1641 if (RI->getFunction() == getAssociatedFunction()) {
1642 auto &PtrOI = OffsetInfoMap[CurPtr];
1643 Changed |= setReachesReturn(PtrOI);
1644 return true;
1645 }
1646 return false;
1647 }
1648
1649 // For PHIs we need to take care of the recurrence explicitly as the value
1650 // might change while we iterate through a loop. For now, we give up if
1651 // the PHI is not invariant.
1652 if (auto *PHI = dyn_cast<PHINode>(Usr)) {
1653 // Note the order here, the Usr access might change the map, CurPtr is
1654 // already in it though.
1655 auto [PhiIt, IsFirstPHIUser] = OffsetInfoMap.try_emplace(PHI);
1656 auto &UsrOI = PhiIt->second;
1657 auto &PtrOI = OffsetInfoMap[CurPtr];
1658
1659 // Check if the PHI operand has already an unknown offset as we can't
1660 // improve on that anymore.
1661 if (PtrOI.isUnknown()) {
1662 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
1663 << *CurPtr << " in " << *PHI << "\n");
1664 Follow = !UsrOI.isUnknown();
1665 UsrOI.setUnknown();
1666 return true;
1667 }
1668
1669 // Check if the PHI is invariant (so far).
1670 if (UsrOI == PtrOI) {
1671 assert(!PtrOI.isUnassigned() &&
1672 "Cannot assign if the current Ptr was not visited!");
1673 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
1674 return true;
1675 }
1676
1677 // Check if the PHI operand can be traced back to AssociatedValue.
1678 APInt Offset(
1679 DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
1680 0);
1681 Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
1682 DL, Offset, /* AllowNonInbounds */ true);
1683 auto It = OffsetInfoMap.find(CurPtrBase);
1684 if (It == OffsetInfoMap.end()) {
1685 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
1686 << *CurPtr << " in " << *PHI
1687 << " (base: " << *CurPtrBase << ")\n");
1688 UsrOI.setUnknown();
1689 Follow = true;
1690 return true;
1691 }
1692
1693 // Check if the PHI operand is not dependent on the PHI itself. Every
1694 // recurrence is a cyclic net of PHIs in the data flow, and has an
1695 // equivalent Cycle in the control flow. One of those PHIs must be in the
1696 // header of that control flow Cycle. This is independent of the choice of
1697 // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
1698 // every Cycle header; if such a node is marked unknown, this will
1699 // eventually propagate through the whole net of PHIs in the recurrence.
1700 const auto *CI =
1701 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
1702 *PHI->getFunction());
1703 if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {
1704 auto BaseOI = It->getSecond();
1705 BaseOI.addToAll(Offset.getZExtValue());
1706 if (IsFirstPHIUser || BaseOI == UsrOI) {
1707 LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
1708 << " in " << *Usr << "\n");
1709 return HandlePassthroughUser(Usr, CurPtr, Follow);
1710 }
1711
1712 LLVM_DEBUG(
1713 dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
1714 << *CurPtr << " in " << *PHI << "\n");
1715 UsrOI.setUnknown();
1716 Follow = true;
1717 return true;
1718 }
1719
1720 UsrOI.merge(PtrOI);
1721 Follow = true;
1722 return true;
1723 }
1724
1725 if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
1726 // If the access is to a pointer that may or may not be the associated
1727 // value, e.g. due to a PHI, we cannot assume it will be read.
1728 AccessKind AK = AccessKind::AK_R;
1729 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1730 AK = AccessKind(AK | AccessKind::AK_MUST);
1731 else
1732 AK = AccessKind(AK | AccessKind::AK_MAY);
1733 if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
1734 OffsetInfoMap[CurPtr].Offsets, Changed,
1735 *LoadI->getType()))
1736 return false;
1737
1738 auto IsAssumption = [](Instruction &I) {
1739 if (auto *II = dyn_cast<IntrinsicInst>(&I))
1740 return II->isAssumeLikeIntrinsic();
1741 return false;
1742 };
1743
1744 auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
1745 // Check if the assumption and the load are executed together without
1746 // memory modification.
1747 do {
1748 if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
1749 return true;
1750 FromI = FromI->getNextNode();
1751 } while (FromI && FromI != ToI);
1752 return false;
1753 };
1754
1755 BasicBlock *BB = LoadI->getParent();
1756 auto IsValidAssume = [&](IntrinsicInst &IntrI) {
1757 if (IntrI.getIntrinsicID() != Intrinsic::assume)
1758 return false;
1759 BasicBlock *IntrBB = IntrI.getParent();
1760 if (IntrI.getParent() == BB) {
1761 if (IsImpactedInRange(LoadI->getNextNode(), &IntrI))
1762 return false;
1763 } else {
1764 auto PredIt = pred_begin(IntrBB);
1765 if (PredIt == pred_end(IntrBB))
1766 return false;
1767 if ((*PredIt) != BB)
1768 return false;
1769 if (++PredIt != pred_end(IntrBB))
1770 return false;
1771 for (auto *SuccBB : successors(BB)) {
1772 if (SuccBB == IntrBB)
1773 continue;
1774 if (isa<UnreachableInst>(SuccBB->getTerminator()))
1775 continue;
1776 return false;
1777 }
1778 if (IsImpactedInRange(LoadI->getNextNode(), BB->getTerminator()))
1779 return false;
1780 if (IsImpactedInRange(&IntrBB->front(), &IntrI))
1781 return false;
1782 }
1783 return true;
1784 };
1785
1786 std::pair<Value *, IntrinsicInst *> Assumption;
1787 for (const Use &LoadU : LoadI->uses()) {
1788 if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
1789 if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
1790 continue;
1791 for (const Use &CmpU : CmpI->uses()) {
1792 if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
1793 if (!IsValidAssume(*IntrI))
1794 continue;
1795 int Idx = CmpI->getOperandUse(0) == LoadU;
1796 Assumption = {CmpI->getOperand(Idx), IntrI};
1797 break;
1798 }
1799 }
1800 }
1801 if (Assumption.first)
1802 break;
1803 }
1804
1805 // Check if we found an assumption associated with this load.
1806 if (!Assumption.first || !Assumption.second)
1807 return true;
1808
1809 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
1810 << *Assumption.second << ": " << *LoadI
1811 << " == " << *Assumption.first << "\n");
1812 bool UsedAssumedInformation = false;
1813 std::optional<Value *> Content = nullptr;
1814 if (Assumption.first)
1815 Content =
1816 A.getAssumedSimplified(*Assumption.first, *this,
1817 UsedAssumedInformation, AA::Interprocedural);
1818 return handleAccess(
1819 A, *Assumption.second, Content, AccessKind::AK_ASSUMPTION,
1820 OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
1821 }
1822
1823 auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
1824 ArrayRef<Value *> OtherOps, AccessKind AK) {
1825 for (auto *OtherOp : OtherOps) {
1826 if (OtherOp == CurPtr) {
1827 LLVM_DEBUG(
1828 dbgs()
1829 << "[AAPointerInfo] Escaping use in store like instruction " << I
1830 << "\n");
1831 return false;
1832 }
1833 }
1834
1835 // If the access is to a pointer that may or may not be the associated
1836 // value, e.g. due to a PHI, we cannot assume it will be written.
1837 if (getUnderlyingObject(CurPtr) == &AssociatedValue)
1838 AK = AccessKind(AK | AccessKind::AK_MUST);
1839 else
1840 AK = AccessKind(AK | AccessKind::AK_MAY);
1841 bool UsedAssumedInformation = false;
1842 std::optional<Value *> Content = nullptr;
1843 if (ValueOp)
1844 Content = A.getAssumedSimplified(
1845 *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
1846 return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
1847 Changed, ValueTy);
1848 };
1849
1850 if (auto *StoreI = dyn_cast<StoreInst>(Usr))
1851 return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
1852 *StoreI->getValueOperand()->getType(),
1853 {StoreI->getValueOperand()}, AccessKind::AK_W);
1854 if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
1855 return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
1856 {RMWI->getValOperand()}, AccessKind::AK_RW);
1857 if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
1858 return HandleStoreLike(
1859 *CXI, nullptr, *CXI->getNewValOperand()->getType(),
1860 {CXI->getCompareOperand(), CXI->getNewValOperand()},
1861 AccessKind::AK_RW);
1862
1863 if (auto *CB = dyn_cast<CallBase>(Usr)) {
1864 if (CB->isLifetimeStartOrEnd())
1865 return true;
1866 const auto *TLI =
1867 A.getInfoCache().getTargetLibraryInfoForFunction(*CB->getFunction());
1868 if (getFreedOperand(CB, TLI) == U)
1869 return true;
1870 if (CB->isArgOperand(&U)) {
1871 unsigned ArgNo = CB->getArgOperandNo(&U);
1872 const auto *CSArgPI = A.getAAFor<AAPointerInfo>(
1873 *this, IRPosition::callsite_argument(*CB, ArgNo),
1875 if (!CSArgPI)
1876 return false;
1877 bool IsArgMustAcc = (getUnderlyingObject(CurPtr) == &AssociatedValue);
1878 Changed = translateAndAddState(A, *CSArgPI, OffsetInfoMap[CurPtr], *CB,
1879 IsArgMustAcc) |
1880 Changed;
1881 if (!CSArgPI->reachesReturn())
1882 return isValidState();
1883
1885 if (!Callee || Callee->arg_size() <= ArgNo)
1886 return false;
1887 bool UsedAssumedInformation = false;
1888 auto ReturnedValue = A.getAssumedSimplified(
1889 IRPosition::returned(*Callee), *this, UsedAssumedInformation,
1891 auto *ReturnedArg =
1892 dyn_cast_or_null<Argument>(ReturnedValue.value_or(nullptr));
1893 auto *Arg = Callee->getArg(ArgNo);
1894 if (ReturnedArg && Arg != ReturnedArg)
1895 return true;
1896 bool IsRetMustAcc = IsArgMustAcc && (ReturnedArg == Arg);
1897 const auto *CSRetPI = A.getAAFor<AAPointerInfo>(
1899 if (!CSRetPI)
1900 return false;
1901 OffsetInfo OI = OffsetInfoMap[CurPtr];
1902 CSArgPI->addReturnedOffsetsTo(OI);
1903 Changed =
1904 translateAndAddState(A, *CSRetPI, OI, *CB, IsRetMustAcc) | Changed;
1905 return isValidState();
1906 }
1907 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
1908 << "\n");
1909 return false;
1910 }
1911
1912 LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
1913 return false;
1914 };
1915 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
1916 assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
1917 assert(!OffsetInfoMap[OldU].isUnassigned() && "Old use should be assinged");
1918 if (OffsetInfoMap.count(NewU)) {
1919 LLVM_DEBUG({
1920 if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
1921 dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
1922 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
1923 << "\n";
1924 }
1925 });
1926 return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
1927 }
1928 bool Unused;
1929 return HandlePassthroughUser(NewU.get(), OldU.get(), Unused);
1930 };
1931 if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
1932 /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
1933 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
1934 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
1935 return indicatePessimisticFixpoint();
1936 }
1937
1938 LLVM_DEBUG({
1939 dbgs() << "Accesses by bin after update:\n";
1940 dumpState(dbgs());
1941 });
1942
1943 return Changed;
1944}
1945
1946struct AAPointerInfoReturned final : AAPointerInfoImpl {
1947 AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
1948 : AAPointerInfoImpl(IRP, A) {}
1949
1950 /// See AbstractAttribute::updateImpl(...).
1951 ChangeStatus updateImpl(Attributor &A) override {
1952 return indicatePessimisticFixpoint();
1953 }
1954
1955 /// See AbstractAttribute::trackStatistics()
1956 void trackStatistics() const override {
1957 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1958 }
1959};
1960
1961struct AAPointerInfoArgument final : AAPointerInfoFloating {
1962 AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
1963 : AAPointerInfoFloating(IRP, A) {}
1964
1965 /// See AbstractAttribute::trackStatistics()
1966 void trackStatistics() const override {
1967 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
1968 }
1969};
1970
1971struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
1972 AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
1973 : AAPointerInfoFloating(IRP, A) {}
1974
1975 /// See AbstractAttribute::updateImpl(...).
1976 ChangeStatus updateImpl(Attributor &A) override {
1977 using namespace AA::PointerInfo;
1978 // We handle memory intrinsics explicitly, at least the first (=
1979 // destination) and second (=source) arguments as we know how they are
1980 // accessed.
1981 if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
1982 int64_t LengthVal = AA::RangeTy::Unknown;
1983 if (auto Length = MI->getLengthInBytes())
1984 LengthVal = Length->getSExtValue();
1985 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
1986 ChangeStatus Changed = ChangeStatus::UNCHANGED;
1987 if (ArgNo > 1) {
1988 LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
1989 << *MI << "\n");
1990 return indicatePessimisticFixpoint();
1991 } else {
1992 auto Kind =
1993 ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
1994 Changed =
1995 Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
1996 }
1997 LLVM_DEBUG({
1998 dbgs() << "Accesses by bin after update:\n";
1999 dumpState(dbgs());
2000 });
2001
2002 return Changed;
2003 }
2004
2005 // TODO: Once we have call site specific value information we can provide
2006 // call site specific liveness information and then it makes
2007 // sense to specialize attributes for call sites arguments instead of
2008 // redirecting requests to the callee argument.
2009 Argument *Arg = getAssociatedArgument();
2010 if (Arg) {
2011 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2012 auto *ArgAA =
2013 A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
2014 if (ArgAA && ArgAA->getState().isValidState())
2015 return translateAndAddStateFromCallee(A, *ArgAA,
2016 *cast<CallBase>(getCtxI()));
2017 if (!Arg->getParent()->isDeclaration())
2018 return indicatePessimisticFixpoint();
2019 }
2020
2021 bool IsKnownNoCapture;
2023 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
2024 return indicatePessimisticFixpoint();
2025
2026 bool IsKnown = false;
2027 if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
2028 return ChangeStatus::UNCHANGED;
2029 bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
2030 auto Kind =
2031 ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
2032 return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
2033 nullptr);
2034 }
2035
2036 /// See AbstractAttribute::trackStatistics()
2037 void trackStatistics() const override {
2038 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2039 }
2040};
2041
2042struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
2043 AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
2044 : AAPointerInfoFloating(IRP, A) {}
2045
2046 /// See AbstractAttribute::trackStatistics()
2047 void trackStatistics() const override {
2048 AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
2049 }
2050};
2051} // namespace
2052
2053/// -----------------------NoUnwind Function Attribute--------------------------
2054
2055namespace {
2056struct AANoUnwindImpl : AANoUnwind {
2057 AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}
2058
2059 /// See AbstractAttribute::initialize(...).
2060 void initialize(Attributor &A) override {
2061 bool IsKnown;
2063 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2064 (void)IsKnown;
2065 }
2066
2067 const std::string getAsStr(Attributor *A) const override {
2068 return getAssumed() ? "nounwind" : "may-unwind";
2069 }
2070
2071 /// See AbstractAttribute::updateImpl(...).
2072 ChangeStatus updateImpl(Attributor &A) override {
2073 auto Opcodes = {
2074 (unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
2075 (unsigned)Instruction::Call, (unsigned)Instruction::CleanupRet,
2076 (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};
2077
2078 auto CheckForNoUnwind = [&](Instruction &I) {
2079 if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
2080 return true;
2081
2082 if (const auto *CB = dyn_cast<CallBase>(&I)) {
2083 bool IsKnownNoUnwind;
2085 A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
2086 IsKnownNoUnwind);
2087 }
2088 return false;
2089 };
2090
2091 bool UsedAssumedInformation = false;
2092 if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
2093 UsedAssumedInformation))
2094 return indicatePessimisticFixpoint();
2095
2096 return ChangeStatus::UNCHANGED;
2097 }
2098};
2099
2100struct AANoUnwindFunction final : public AANoUnwindImpl {
2101 AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
2102 : AANoUnwindImpl(IRP, A) {}
2103
2104 /// See AbstractAttribute::trackStatistics()
2105 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
2106};
2107
2108/// NoUnwind attribute deduction for a call sites.
2109struct AANoUnwindCallSite final
2110 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {
2111 AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
2112 : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl>(IRP, A) {}
2113
2114 /// See AbstractAttribute::trackStatistics()
2115 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
2116};
2117} // namespace
2118
2119/// ------------------------ NoSync Function Attribute -------------------------
2120
2121bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
2122 switch (CB.getIntrinsicID()) {
2123 case Intrinsic::nvvm_barrier_cta_sync_aligned_all:
2124 case Intrinsic::nvvm_barrier_cta_sync_aligned_count:
2125 case Intrinsic::nvvm_barrier_cta_red_and_aligned_all:
2126 case Intrinsic::nvvm_barrier_cta_red_and_aligned_count:
2127 case Intrinsic::nvvm_barrier_cta_red_or_aligned_all:
2128 case Intrinsic::nvvm_barrier_cta_red_or_aligned_count:
2129 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_all:
2130 case Intrinsic::nvvm_barrier_cta_red_popc_aligned_count:
2131 return true;
2132 case Intrinsic::amdgcn_s_barrier:
2133 if (ExecutedAligned)
2134 return true;
2135 break;
2136 default:
2137 break;
2138 }
2139 return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
2140}
2141
2143 if (!I->isAtomic())
2144 return false;
2145
2146 if (auto *FI = dyn_cast<FenceInst>(I))
2147 // All legal orderings for fence are stronger than monotonic.
2148 return FI->getSyncScopeID() != SyncScope::SingleThread;
2149 if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
2150 // Unordered is not a legal ordering for cmpxchg.
2151 return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
2152 AI->getFailureOrdering() != AtomicOrdering::Monotonic);
2153 }
2154
2155 AtomicOrdering Ordering;
2156 switch (I->getOpcode()) {
2157 case Instruction::AtomicRMW:
2158 Ordering = cast<AtomicRMWInst>(I)->getOrdering();
2159 break;
2160 case Instruction::Store:
2161 Ordering = cast<StoreInst>(I)->getOrdering();
2162 break;
2163 case Instruction::Load:
2164 Ordering = cast<LoadInst>(I)->getOrdering();
2165 break;
2166 default:
2168 "New atomic operations need to be known in the attributor.");
2169 }
2170
2171 return (Ordering != AtomicOrdering::Unordered &&
2172 Ordering != AtomicOrdering::Monotonic);
2173}
2174
2175namespace {
2176struct AANoSyncImpl : AANoSync {
2177 AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}
2178
2179 /// See AbstractAttribute::initialize(...).
2180 void initialize(Attributor &A) override {
2181 bool IsKnown;
2182 assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),
2183 DepClassTy::NONE, IsKnown));
2184 (void)IsKnown;
2185 }
2186
2187 const std::string getAsStr(Attributor *A) const override {
2188 return getAssumed() ? "nosync" : "may-sync";
2189 }
2190
2191 /// See AbstractAttribute::updateImpl(...).
2192 ChangeStatus updateImpl(Attributor &A) override;
2193};
2194
2195ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {
2196
2197 auto CheckRWInstForNoSync = [&](Instruction &I) {
2198 return AA::isNoSyncInst(A, I, *this);
2199 };
2200
2201 auto CheckForNoSync = [&](Instruction &I) {
2202 // At this point we handled all read/write effects and they are all
2203 // nosync, so they can be skipped.
2204 if (I.mayReadOrWriteMemory())
2205 return true;
2206
2207 bool IsKnown;
2208 CallBase &CB = cast<CallBase>(I);
2211 IsKnown))
2212 return true;
2213
2214 // non-convergent and readnone imply nosync.
2215 return !CB.isConvergent();
2216 };
2217
2218 bool UsedAssumedInformation = false;
2219 if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
2220 UsedAssumedInformation) ||
2221 !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
2222 UsedAssumedInformation))
2223 return indicatePessimisticFixpoint();
2224
2226}
2227
2228struct AANoSyncFunction final : public AANoSyncImpl {
2229 AANoSyncFunction(const IRPosition &IRP, Attributor &A)
2230 : AANoSyncImpl(IRP, A) {}
2231
2232 /// See AbstractAttribute::trackStatistics()
2233 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
2234};
2235
2236/// NoSync attribute deduction for a call sites.
2237struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {
2238 AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
2239 : AACalleeToCallSite<AANoSync, AANoSyncImpl>(IRP, A) {}
2240
2241 /// See AbstractAttribute::trackStatistics()
2242 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
2243};
2244} // namespace
2245
2246/// ------------------------ No-Free Attributes ----------------------------
2247
2248namespace {
2249struct AANoFreeImpl : public AANoFree {
2250 AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}
2251
2252 /// See AbstractAttribute::initialize(...).
2253 void initialize(Attributor &A) override {
2254 bool IsKnown;
2255 assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),
2256 DepClassTy::NONE, IsKnown));
2257 (void)IsKnown;
2258 }
2259
2260 /// See AbstractAttribute::updateImpl(...).
2261 ChangeStatus updateImpl(Attributor &A) override {
2262 auto CheckForNoFree = [&](Instruction &I) {
2263 if (auto *CB = dyn_cast<CallBase>(&I)) {
2264 bool IsKnown;
2266 A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
2267 IsKnown);
2268 }
2269 // Make sure that synchronization cannot establish happens-before with a
2270 // free on another thread.
2271 return AA::isNoSyncInst(A, I, *this);
2272 };
2273
2274 bool UsedAssumedInformation = false;
2275 if (!A.checkForAllReadWriteInstructions(CheckForNoFree, *this,
2276 UsedAssumedInformation) ||
2277 !A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
2278 UsedAssumedInformation))
2279 return indicatePessimisticFixpoint();
2280
2281 return ChangeStatus::UNCHANGED;
2282 }
2283
2284 /// See AbstractAttribute::getAsStr().
2285 const std::string getAsStr(Attributor *A) const override {
2286 return getAssumed() ? "nofree" : "may-free";
2287 }
2288};
2289
2290struct AANoFreeFunction final : public AANoFreeImpl {
2291 AANoFreeFunction(const IRPosition &IRP, Attributor &A)
2292 : AANoFreeImpl(IRP, A) {}
2293
2294 /// See AbstractAttribute::trackStatistics()
2295 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
2296};
2297
2298/// NoFree attribute deduction for a call sites.
2299struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {
2300 AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
2301 : AACalleeToCallSite<AANoFree, AANoFreeImpl>(IRP, A) {}
2302
2303 /// See AbstractAttribute::trackStatistics()
2304 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
2305};
2306
2307/// NoFree attribute for floating values.
2308struct AANoFreeFloating : AANoFreeImpl {
2309 AANoFreeFloating(const IRPosition &IRP, Attributor &A)
2310 : AANoFreeImpl(IRP, A) {}
2311
2312 /// See AbstractAttribute::trackStatistics()
2313 void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}
2314
2315 /// See Abstract Attribute::updateImpl(...).
2316 ChangeStatus updateImpl(Attributor &A) override {
2317 const IRPosition &IRP = getIRPosition();
2318
2319 bool IsKnown;
2322 DepClassTy::OPTIONAL, IsKnown))
2323 return ChangeStatus::UNCHANGED;
2324
2325 Value &AssociatedValue = getIRPosition().getAssociatedValue();
2326 auto Pred = [&](const Use &U, bool &Follow) -> bool {
2327 Instruction *UserI = cast<Instruction>(U.getUser());
2328 if (auto *CB = dyn_cast<CallBase>(UserI)) {
2329 if (CB->isBundleOperand(&U))
2330 return false;
2331 if (!CB->isArgOperand(&U))
2332 return true;
2333 unsigned ArgNo = CB->getArgOperandNo(&U);
2334
2335 // Even if the argument is nofree, we still need to check for nocapture,
2336 // as the call may capture the argument without freeing it, and the
2337 // captured argument is freed later.
2338 bool IsKnown;
2340 A, this, IRPosition::callsite_argument(*CB, ArgNo),
2341 DepClassTy::REQUIRED, IsKnown))
2342 return false;
2343
2344 const AANoCapture *NoCaptureAA = nullptr;
2346 A, this, IRPosition::callsite_argument(*CB, ArgNo),
2347 DepClassTy::REQUIRED, IsKnown,
2348 /*IgnoreSubsumingPositions=*/false, &NoCaptureAA)) {
2349 if (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
2350 Follow = true;
2351 return true;
2352 }
2353 return false;
2354 }
2355
2356 return true;
2357 }
2358
2359 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
2360 if (!capturesAnyProvenance(CI))
2361 return true;
2363 Follow = true;
2364 return true;
2365 }
2366
2367 if (isa<ReturnInst>(UserI) && getIRPosition().isArgumentPosition())
2368 return true;
2369
2370 // Capturing user.
2371 return false;
2372 };
2373 if (!A.checkForAllUses(Pred, *this, AssociatedValue))
2374 return indicatePessimisticFixpoint();
2375
2376 return ChangeStatus::UNCHANGED;
2377 }
2378};
2379
2380/// NoFree attribute for a call site argument.
2381struct AANoFreeArgument final : AANoFreeFloating {
2382 AANoFreeArgument(const IRPosition &IRP, Attributor &A)
2383 : AANoFreeFloating(IRP, A) {}
2384
2385 /// See AbstractAttribute::trackStatistics()
2386 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
2387};
2388
2389/// NoFree attribute for call site arguments.
2390struct AANoFreeCallSiteArgument final : AANoFreeFloating {
2391 AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
2392 : AANoFreeFloating(IRP, A) {}
2393
2394 /// See AbstractAttribute::updateImpl(...).
2395 ChangeStatus updateImpl(Attributor &A) override {
2396 // TODO: Once we have call site specific value information we can provide
2397 // call site specific liveness information and then it makes
2398 // sense to specialize attributes for call sites arguments instead of
2399 // redirecting requests to the callee argument.
2400 Argument *Arg = getAssociatedArgument();
2401 if (!Arg)
2402 return indicatePessimisticFixpoint();
2403 const IRPosition &ArgPos = IRPosition::argument(*Arg);
2404 bool IsKnown;
2406 DepClassTy::REQUIRED, IsKnown))
2407 return ChangeStatus::UNCHANGED;
2408 return indicatePessimisticFixpoint();
2409 }
2410
2411 /// See AbstractAttribute::trackStatistics()
2412 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nofree) };
2413};
2414
2415/// NoFree attribute for function return value.
2416struct AANoFreeReturned final : AANoFreeFloating {
2417 AANoFreeReturned(const IRPosition &IRP, Attributor &A)
2418 : AANoFreeFloating(IRP, A) {
2419 llvm_unreachable("NoFree is not applicable to function returns!");
2420 }
2421
2422 /// See AbstractAttribute::initialize(...).
2423 void initialize(Attributor &A) override {
2424 llvm_unreachable("NoFree is not applicable to function returns!");
2425 }
2426
2427 /// See AbstractAttribute::updateImpl(...).
2428 ChangeStatus updateImpl(Attributor &A) override {
2429 llvm_unreachable("NoFree is not applicable to function returns!");
2430 }
2431
2432 /// See AbstractAttribute::trackStatistics()
2433 void trackStatistics() const override {}
2434};
2435
2436/// NoFree attribute deduction for a call site return value.
2437struct AANoFreeCallSiteReturned final : AANoFreeFloating {
2438 AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
2439 : AANoFreeFloating(IRP, A) {}
2440
2441 ChangeStatus manifest(Attributor &A) override {
2442 return ChangeStatus::UNCHANGED;
2443 }
2444 /// See AbstractAttribute::trackStatistics()
2445 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
2446};
2447} // namespace
2448
2449/// ------------------------ NonNull Argument Attribute ------------------------
2450
2452 Attribute::AttrKind ImpliedAttributeKind,
2453 bool IgnoreSubsumingPositions) {
2455 AttrKinds.push_back(Attribute::NonNull);
2458 AttrKinds.push_back(Attribute::Dereferenceable);
2459 if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
2460 return true;
2461
2462 DominatorTree *DT = nullptr;
2463 AssumptionCache *AC = nullptr;
2464 InformationCache &InfoCache = A.getInfoCache();
2465 if (const Function *Fn = IRP.getAnchorScope()) {
2466 if (!Fn->isDeclaration()) {
2469 }
2470 }
2471
2473 if (IRP.getPositionKind() != IRP_RETURNED) {
2474 Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});
2475 } else {
2476 bool UsedAssumedInformation = false;
2477 if (!A.checkForAllInstructions(
2478 [&](Instruction &I) {
2479 Worklist.push_back({*cast<ReturnInst>(I).getReturnValue(), &I});
2480 return true;
2481 },
2482 IRP.getAssociatedFunction(), nullptr, {Instruction::Ret},
2483 UsedAssumedInformation, false, /*CheckPotentiallyDead=*/true))
2484 return false;
2485 }
2486
2487 if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) {
2488 return !isKnownNonZero(
2489 VAC.getValue(),
2490 SimplifyQuery(A.getDataLayout(), DT, AC, VAC.getCtxI()));
2491 }))
2492 return false;
2493
2494 A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
2495 Attribute::NonNull)});
2496 return true;
2497}
2498
2499namespace {
2500static int64_t getKnownNonNullAndDerefBytesForUse(
2501 Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
2502 const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
2503 TrackUse = false;
2504
2505 const Value *UseV = U->get();
2506 if (!UseV->getType()->isPointerTy())
2507 return 0;
2508
2509 // We need to follow common pointer manipulation uses to the accesses they
2510 // feed into. We can try to be smart to avoid looking through things we do not
2511 // like for now, e.g., non-inbounds GEPs.
2512 if (isa<CastInst>(I)) {
2513 TrackUse = true;
2514 return 0;
2515 }
2516
2518 TrackUse = true;
2519 return 0;
2520 }
2521
2522 Type *PtrTy = UseV->getType();
2523 const Function *F = I->getFunction();
2526 const DataLayout &DL = A.getInfoCache().getDL();
2527 if (const auto *CB = dyn_cast<CallBase>(I)) {
2528 if (CB->isBundleOperand(U)) {
2529 if (RetainedKnowledge RK = getKnowledgeFromUse(
2530 U, {Attribute::NonNull, Attribute::Dereferenceable})) {
2531 IsNonNull |=
2532 (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
2533 return RK.ArgValue;
2534 }
2535 return 0;
2536 }
2537
2538 if (CB->isCallee(U)) {
2539 IsNonNull |= !NullPointerIsDefined;
2540 return 0;
2541 }
2542
2543 unsigned ArgNo = CB->getArgOperandNo(U);
2544 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
2545 // As long as we only use known information there is no need to track
2546 // dependences here.
2547 bool IsKnownNonNull;
2549 DepClassTy::NONE, IsKnownNonNull);
2550 IsNonNull |= IsKnownNonNull;
2551 auto *DerefAA =
2552 A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
2553 return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
2554 }
2555
2556 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
2557 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() ||
2558 Loc->Size.isScalable() || I->isVolatile())
2559 return 0;
2560
2561 int64_t Offset;
2562 const Value *Base =
2563 getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
2564 if (Base && Base == &AssociatedValue) {
2565 int64_t DerefBytes = Loc->Size.getValue() + Offset;
2566 IsNonNull |= !NullPointerIsDefined;
2567 return std::max(int64_t(0), DerefBytes);
2568 }
2569
2570 /// Corner case when an offset is 0.
2572 /*AllowNonInbounds*/ true);
2573 if (Base && Base == &AssociatedValue && Offset == 0) {
2574 int64_t DerefBytes = Loc->Size.getValue();
2575 IsNonNull |= !NullPointerIsDefined;
2576 return std::max(int64_t(0), DerefBytes);
2577 }
2578
2579 return 0;
2580}
2581
2582struct AANonNullImpl : AANonNull {
2583 AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}
2584
2585 /// See AbstractAttribute::initialize(...).
2586 void initialize(Attributor &A) override {
2587 Value &V = *getAssociatedValue().stripPointerCasts();
2588 if (isa<ConstantPointerNull>(V)) {
2589 indicatePessimisticFixpoint();
2590 return;
2591 }
2592
2593 if (Instruction *CtxI = getCtxI())
2594 followUsesInMBEC(*this, A, getState(), *CtxI);
2595 }
2596
2597 /// See followUsesInMBEC
2598 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
2599 AANonNull::StateType &State) {
2600 bool IsNonNull = false;
2601 bool TrackUse = false;
2602 getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
2603 IsNonNull, TrackUse);
2604 State.setKnown(IsNonNull);
2605 return TrackUse;
2606 }
2607
2608 /// See AbstractAttribute::getAsStr().
2609 const std::string getAsStr(Attributor *A) const override {
2610 return getAssumed() ? "nonnull" : "may-null";
2611 }
2612};
2613
2614/// NonNull attribute for a floating value.
2615struct AANonNullFloating : public AANonNullImpl {
2616 AANonNullFloating(const IRPosition &IRP, Attributor &A)
2617 : AANonNullImpl(IRP, A) {}
2618
2619 /// See AbstractAttribute::updateImpl(...).
2620 ChangeStatus updateImpl(Attributor &A) override {
2621 auto CheckIRP = [&](const IRPosition &IRP) {
2622 bool IsKnownNonNull;
2624 A, *this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
2625 };
2626
2627 bool Stripped;
2628 bool UsedAssumedInformation = false;
2629 Value *AssociatedValue = &getAssociatedValue();
2631 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
2632 AA::AnyScope, UsedAssumedInformation))
2633 Stripped = false;
2634 else
2635 Stripped =
2636 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
2637
2638 if (!Stripped) {
2639 bool IsKnown;
2640 if (auto *PHI = dyn_cast<PHINode>(AssociatedValue))
2641 if (llvm::all_of(PHI->incoming_values(), [&](Value *Op) {
2642 return AA::hasAssumedIRAttr<Attribute::NonNull>(
2643 A, this, IRPosition::value(*Op), DepClassTy::OPTIONAL,
2644 IsKnown);
2645 }))
2646 return ChangeStatus::UNCHANGED;
2647 if (auto *Select = dyn_cast<SelectInst>(AssociatedValue))
2649 A, this, IRPosition::value(*Select->getFalseValue()),
2650 DepClassTy::OPTIONAL, IsKnown) &&
2652 A, this, IRPosition::value(*Select->getTrueValue()),
2653 DepClassTy::OPTIONAL, IsKnown))
2654 return ChangeStatus::UNCHANGED;
2655
2656 // If we haven't stripped anything we might still be able to use a
2657 // different AA, but only if the IRP changes. Effectively when we
2658 // interpret this not as a call site value but as a floating/argument
2659 // value.
2660 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
2661 if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
2662 return indicatePessimisticFixpoint();
2663 return ChangeStatus::UNCHANGED;
2664 }
2665
2666 for (const auto &VAC : Values)
2667 if (!CheckIRP(IRPosition::value(*VAC.getValue())))
2668 return indicatePessimisticFixpoint();
2669
2670 return ChangeStatus::UNCHANGED;
2671 }
2672
2673 /// See AbstractAttribute::trackStatistics()
2674 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2675};
2676
2677/// NonNull attribute for function return value.
2678struct AANonNullReturned final
2679 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2680 false, AANonNull::IRAttributeKind, false> {
2681 AANonNullReturned(const IRPosition &IRP, Attributor &A)
2682 : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
2683 false, Attribute::NonNull, false>(IRP, A) {
2684 }
2685
2686 /// See AbstractAttribute::getAsStr().
2687 const std::string getAsStr(Attributor *A) const override {
2688 return getAssumed() ? "nonnull" : "may-null";
2689 }
2690
2691 /// See AbstractAttribute::trackStatistics()
2692 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
2693};
2694
2695/// NonNull attribute for function argument.
2696struct AANonNullArgument final
2697 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {
2698 AANonNullArgument(const IRPosition &IRP, Attributor &A)
2699 : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl>(IRP, A) {}
2700
2701 /// See AbstractAttribute::trackStatistics()
2702 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
2703};
2704
2705struct AANonNullCallSiteArgument final : AANonNullFloating {
2706 AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
2707 : AANonNullFloating(IRP, A) {}
2708
2709 /// See AbstractAttribute::trackStatistics()
2710 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
2711};
2712
2713/// NonNull attribute for a call site return position.
2714struct AANonNullCallSiteReturned final
2715 : AACalleeToCallSite<AANonNull, AANonNullImpl> {
2716 AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
2717 : AACalleeToCallSite<AANonNull, AANonNullImpl>(IRP, A) {}
2718
2719 /// See AbstractAttribute::trackStatistics()
2720 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
2721};
2722} // namespace
2723
2724/// ------------------------ Must-Progress Attributes --------------------------
2725namespace {
2726struct AAMustProgressImpl : public AAMustProgress {
2727 AAMustProgressImpl(const IRPosition &IRP, Attributor &A)
2728 : AAMustProgress(IRP, A) {}
2729
2730 /// See AbstractAttribute::initialize(...).
2731 void initialize(Attributor &A) override {
2732 bool IsKnown;
2734 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2735 (void)IsKnown;
2736 }
2737
2738 /// See AbstractAttribute::getAsStr()
2739 const std::string getAsStr(Attributor *A) const override {
2740 return getAssumed() ? "mustprogress" : "may-not-progress";
2741 }
2742};
2743
2744struct AAMustProgressFunction final : AAMustProgressImpl {
2745 AAMustProgressFunction(const IRPosition &IRP, Attributor &A)
2746 : AAMustProgressImpl(IRP, A) {}
2747
2748 /// See AbstractAttribute::updateImpl(...).
2749 ChangeStatus updateImpl(Attributor &A) override {
2750 bool IsKnown;
2752 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
2753 if (IsKnown)
2754 return indicateOptimisticFixpoint();
2755 return ChangeStatus::UNCHANGED;
2756 }
2757
2758 auto CheckForMustProgress = [&](AbstractCallSite ACS) {
2759 IRPosition IPos = IRPosition::callsite_function(*ACS.getInstruction());
2760 bool IsKnownMustProgress;
2762 A, this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
2763 /* IgnoreSubsumingPositions */ true);
2764 };
2765
2766 bool AllCallSitesKnown = true;
2767 if (!A.checkForAllCallSites(CheckForMustProgress, *this,
2768 /* RequireAllCallSites */ true,
2769 AllCallSitesKnown))
2770 return indicatePessimisticFixpoint();
2771
2772 return ChangeStatus::UNCHANGED;
2773 }
2774
2775 /// See AbstractAttribute::trackStatistics()
2776 void trackStatistics() const override {
2777 STATS_DECLTRACK_FN_ATTR(mustprogress)
2778 }
2779};
2780
2781/// MustProgress attribute deduction for a call sites.
2782struct AAMustProgressCallSite final : AAMustProgressImpl {
2783 AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)
2784 : AAMustProgressImpl(IRP, A) {}
2785
2786 /// See AbstractAttribute::updateImpl(...).
2787 ChangeStatus updateImpl(Attributor &A) override {
2788 // TODO: Once we have call site specific value information we can provide
2789 // call site specific liveness information and then it makes
2790 // sense to specialize attributes for call sites arguments instead of
2791 // redirecting requests to the callee argument.
2792 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
2793 bool IsKnownMustProgress;
2795 A, this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
2796 return indicatePessimisticFixpoint();
2797 return ChangeStatus::UNCHANGED;
2798 }
2799
2800 /// See AbstractAttribute::trackStatistics()
2801 void trackStatistics() const override {
2802 STATS_DECLTRACK_CS_ATTR(mustprogress);
2803 }
2804};
2805} // namespace
2806
2807/// ------------------------ No-Recurse Attributes ----------------------------
2808
2809namespace {
2810struct AANoRecurseImpl : public AANoRecurse {
2811 AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}
2812
2813 /// See AbstractAttribute::initialize(...).
2814 void initialize(Attributor &A) override {
2815 bool IsKnown;
2817 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
2818 (void)IsKnown;
2819 }
2820
2821 /// See AbstractAttribute::getAsStr()
2822 const std::string getAsStr(Attributor *A) const override {
2823 return getAssumed() ? "norecurse" : "may-recurse";
2824 }
2825};
2826
2827struct AANoRecurseFunction final : AANoRecurseImpl {
2828 AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
2829 : AANoRecurseImpl(IRP, A) {}
2830
2831 /// See AbstractAttribute::updateImpl(...).
2832 ChangeStatus updateImpl(Attributor &A) override {
2833
2834 // If all live call sites are known to be no-recurse, we are as well.
2835 auto CallSitePred = [&](AbstractCallSite ACS) {
2836 bool IsKnownNoRecurse;
2838 A, this,
2839 IRPosition::function(*ACS.getInstruction()->getFunction()),
2840 DepClassTy::NONE, IsKnownNoRecurse))
2841 return false;
2842 return IsKnownNoRecurse;
2843 };
2844 bool UsedAssumedInformation = false;
2845 if (A.checkForAllCallSites(CallSitePred, *this, true,
2846 UsedAssumedInformation)) {
2847 // If we know all call sites and all are known no-recurse, we are done.
2848 // If all known call sites, which might not be all that exist, are known
2849 // to be no-recurse, we are not done but we can continue to assume
2850 // no-recurse. If one of the call sites we have not visited will become
2851 // live, another update is triggered.
2852 if (!UsedAssumedInformation)
2853 indicateOptimisticFixpoint();
2854 return ChangeStatus::UNCHANGED;
2855 }
2856
2857 const AAInterFnReachability *EdgeReachability =
2858 A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
2859 DepClassTy::REQUIRED);
2860 if (EdgeReachability && EdgeReachability->canReach(A, *getAnchorScope()))
2861 return indicatePessimisticFixpoint();
2862 return ChangeStatus::UNCHANGED;
2863 }
2864
2865 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
2866};
2867
2868/// NoRecurse attribute deduction for a call sites.
2869struct AANoRecurseCallSite final
2870 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {
2871 AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
2872 : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl>(IRP, A) {}
2873
2874 /// See AbstractAttribute::trackStatistics()
2875 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
2876};
2877} // namespace
2878
2879/// ------------------------ No-Convergent Attribute --------------------------
2880
2881namespace {
2882struct AANonConvergentImpl : public AANonConvergent {
2883 AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
2884 : AANonConvergent(IRP, A) {}
2885
2886 /// See AbstractAttribute::getAsStr()
2887 const std::string getAsStr(Attributor *A) const override {
2888 return getAssumed() ? "non-convergent" : "may-be-convergent";
2889 }
2890};
2891
2892struct AANonConvergentFunction final : AANonConvergentImpl {
2893 AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
2894 : AANonConvergentImpl(IRP, A) {}
2895
2896 /// See AbstractAttribute::updateImpl(...).
2897 ChangeStatus updateImpl(Attributor &A) override {
2898 // If all function calls are known to not be convergent, we are not
2899 // convergent.
2900 auto CalleeIsNotConvergent = [&](Instruction &Inst) {
2901 CallBase &CB = cast<CallBase>(Inst);
2903 if (!Callee || Callee->isIntrinsic()) {
2904 return false;
2905 }
2906 if (Callee->isDeclaration()) {
2907 return !Callee->hasFnAttribute(Attribute::Convergent);
2908 }
2909 const auto *ConvergentAA = A.getAAFor<AANonConvergent>(
2910 *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);
2911 return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
2912 };
2913
2914 bool UsedAssumedInformation = false;
2915 if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,
2916 UsedAssumedInformation)) {
2917 return indicatePessimisticFixpoint();
2918 }
2919 return ChangeStatus::UNCHANGED;
2920 }
2921
2922 ChangeStatus manifest(Attributor &A) override {
2923 if (isKnownNotConvergent() &&
2924 A.hasAttr(getIRPosition(), Attribute::Convergent)) {
2925 A.removeAttrs(getIRPosition(), {Attribute::Convergent});
2926 return ChangeStatus::CHANGED;
2927 }
2928 return ChangeStatus::UNCHANGED;
2929 }
2930
2931 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }
2932};
2933} // namespace
2934
2935/// -------------------- Undefined-Behavior Attributes ------------------------
2936
2937namespace {
2938struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
2939 AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
2940 : AAUndefinedBehavior(IRP, A) {}
2941
2942 struct UBInfo {
2943 enum Kind {
2944 NullPtrAccess,
2945 UndefPtrAccess,
2946 UndefBranchCondition,
2947 UndefReturnValue,
2948 NullReturnViolatesNonNull,
2949 UndefCallArgument,
2950 NullArgViolatesNonNull,
2951 };
2952
2953 Kind K;
2954 std::optional<unsigned> ArgNo;
2955
2956 UBInfo(Kind K) : K(K), ArgNo(std::nullopt) {}
2957
2958 UBInfo(Kind K, std::optional<unsigned> ArgNo) : K(K), ArgNo(ArgNo) {}
2959 };
2960
2961 /// See AbstractAttribute::updateImpl(...).
2962 // through a pointer (i.e. also branches etc.)
2963 ChangeStatus updateImpl(Attributor &A) override {
2964 const size_t UBPrevSize = KnownUBInsts.size();
2965 const size_t NoUBPrevSize = AssumedNoUBInsts.size();
2966
2967 auto InspectMemAccessInstForUB = [&](Instruction &I) {
2968 // Volatile accesses on null are not necessarily UB.
2969 if (I.isVolatile())
2970 return true;
2971
2972 // Skip instructions that are already saved.
2973 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
2974 return true;
2975
2976 // If we reach here, we know we have an instruction
2977 // that accesses memory through a pointer operand,
2978 // for which getPointerOperand() should give it to us.
2979 Value *PtrOp =
2980 const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
2981 assert(PtrOp &&
2982 "Expected pointer operand of memory accessing instruction");
2983
2984 // Either we stopped and the appropriate action was taken,
2985 // or we got back a simplified value to continue.
2986 std::optional<Value *> SimplifiedPtrOp =
2987 stopOnUndefOrAssumed(A, PtrOp, &I, UBInfo::UndefPtrAccess);
2988 if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
2989 return true;
2990 const Value *PtrOpVal = *SimplifiedPtrOp;
2991
2992 // A memory access through a pointer is considered UB
2993 // only if the pointer has constant null value.
2994 // TODO: Expand it to not only check constant values.
2995 if (!isa<ConstantPointerNull>(PtrOpVal)) {
2996 AssumedNoUBInsts.insert(&I);
2997 return true;
2998 }
2999 const Type *PtrTy = PtrOpVal->getType();
3000
3001 // Because we only consider instructions inside functions,
3002 // assume that a parent function exists.
3003 const Function *F = I.getFunction();
3004
3005 // A memory access using constant null pointer is only considered UB
3006 // if null pointer is _not_ defined for the target platform.
3008 AssumedNoUBInsts.insert(&I);
3009 else
3010 KnownUBInsts.try_emplace(&I, UBInfo::NullPtrAccess);
3011 return true;
3012 };
3013
3014 auto InspectBrInstForUB = [&](Instruction &I) {
3015 // A conditional branch instruction is considered UB if it has `undef`
3016 // condition.
3017
3018 // Skip instructions that are already saved.
3019 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3020 return true;
3021
3022 // We know we have a branch instruction.
3023 auto *BrInst = cast<CondBrInst>(&I);
3024
3025 // Either we stopped and the appropriate action was taken,
3026 // or we got back a simplified value to continue.
3027 std::optional<Value *> SimplifiedCond = stopOnUndefOrAssumed(
3028 A, BrInst->getCondition(), BrInst, UBInfo::UndefBranchCondition);
3029 if (!SimplifiedCond || !*SimplifiedCond)
3030 return true;
3031 AssumedNoUBInsts.insert(&I);
3032 return true;
3033 };
3034
3035 auto InspectCallSiteForUB = [&](Instruction &I) {
3036 // Check whether a callsite always cause UB or not
3037
3038 // Skip instructions that are already saved.
3039 if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
3040 return true;
3041
3042 // Check nonnull and noundef argument attribute violation for each
3043 // callsite.
3044 CallBase &CB = cast<CallBase>(I);
3046 if (!Callee)
3047 return true;
3048 for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
3049 // If current argument is known to be simplified to null pointer and the
3050 // corresponding argument position is known to have nonnull attribute,
3051 // the argument is poison. Furthermore, if the argument is poison and
3052 // the position is known to have noundef attriubte, this callsite is
3053 // considered UB.
3054 if (idx >= Callee->arg_size())
3055 break;
3056 Value *ArgVal = CB.getArgOperand(idx);
3057 if (!ArgVal)
3058 continue;
3059 // Here, we handle three cases.
3060 // (1) Not having a value means it is dead. (we can replace the value
3061 // with undef)
3062 // (2) Simplified to undef. The argument violate noundef attriubte.
3063 // (3) Simplified to null pointer where known to be nonnull.
3064 // The argument is a poison value and violate noundef attribute.
3065 IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
3066 bool IsKnownNoUndef;
3068 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
3069 if (!IsKnownNoUndef)
3070 continue;
3071 bool UsedAssumedInformation = false;
3072 std::optional<Value *> SimplifiedVal =
3073 A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
3074 UsedAssumedInformation, AA::Interprocedural);
3075 if (UsedAssumedInformation)
3076 continue;
3077 if (SimplifiedVal && !*SimplifiedVal)
3078 return true;
3079 if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
3080 KnownUBInsts.try_emplace(&I, UBInfo(UBInfo::UndefCallArgument, idx));
3081 continue;
3082 }
3083 if (!ArgVal->getType()->isPointerTy() ||
3084 !isa<ConstantPointerNull>(**SimplifiedVal))
3085 continue;
3086 bool IsKnownNonNull;
3088 A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
3089 if (IsKnownNonNull)
3090 KnownUBInsts.try_emplace(&I,
3091 UBInfo(UBInfo::NullArgViolatesNonNull, idx));
3092 }
3093 return true;
3094 };
3095
3096 auto InspectReturnInstForUB = [&](Instruction &I) {
3097 auto &RI = cast<ReturnInst>(I);
3098 // Either we stopped and the appropriate action was taken,
3099 // or we got back a simplified return value to continue.
3100 std::optional<Value *> SimplifiedRetValue = stopOnUndefOrAssumed(
3101 A, RI.getReturnValue(), &I, UBInfo::UndefReturnValue);
3102 if (!SimplifiedRetValue || !*SimplifiedRetValue)
3103 return true;
3104
3105 // Check if a return instruction always cause UB or not
3106 // Note: It is guaranteed that the returned position of the anchor
3107 // scope has noundef attribute when this is called.
3108 // We also ensure the return position is not "assumed dead"
3109 // because the returned value was then potentially simplified to
3110 // `undef` in AAReturnedValues without removing the `noundef`
3111 // attribute yet.
3112
3113 // When the returned position has noundef attriubte, UB occurs in the
3114 // following cases.
3115 // (1) Returned value is known to be undef.
3116 // (2) The value is known to be a null pointer and the returned
3117 // position has nonnull attribute (because the returned value is
3118 // poison).
3119 if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
3120 bool IsKnownNonNull;
3122 A, this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE,
3123 IsKnownNonNull);
3124 if (IsKnownNonNull)
3125 KnownUBInsts.try_emplace(&I, UBInfo::NullReturnViolatesNonNull);
3126 }
3127
3128 return true;
3129 };
3130
3131 bool UsedAssumedInformation = false;
3132 A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
3133 {Instruction::Load, Instruction::Store,
3134 Instruction::AtomicCmpXchg,
3135 Instruction::AtomicRMW},
3136 UsedAssumedInformation,
3137 /* CheckBBLivenessOnly */ true);
3138 A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::CondBr},
3139 UsedAssumedInformation,
3140 /* CheckBBLivenessOnly */ true);
3141 A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
3142 UsedAssumedInformation);
3143
3144 // If the returned position of the anchor scope has noundef attriubte, check
3145 // all returned instructions.
3146 if (!getAnchorScope()->getReturnType()->isVoidTy()) {
3147 const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
3148 if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
3149 bool IsKnownNoUndef;
3151 A, this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
3152 if (IsKnownNoUndef)
3153 A.checkForAllInstructions(InspectReturnInstForUB, *this,
3154 {Instruction::Ret}, UsedAssumedInformation,
3155 /* CheckBBLivenessOnly */ true);
3156 }
3157 }
3158
3159 if (NoUBPrevSize != AssumedNoUBInsts.size() ||
3160 UBPrevSize != KnownUBInsts.size())
3161 return ChangeStatus::CHANGED;
3162 return ChangeStatus::UNCHANGED;
3163 }
3164
3165 bool isKnownToCauseUB(Instruction *I) const override {
3166 return KnownUBInsts.count(I);
3167 }
3168
3169 bool isAssumedToCauseUB(Instruction *I) const override {
3170 // In simple words, if an instruction is not in the assumed to _not_
3171 // cause UB, then it is assumed UB (that includes those
3172 // in the KnownUBInsts set). The rest is boilerplate
3173 // is to ensure that it is one of the instructions we test
3174 // for UB.
3175
3176 switch (I->getOpcode()) {
3177 case Instruction::Load:
3178 case Instruction::Store:
3179 case Instruction::AtomicCmpXchg:
3180 case Instruction::AtomicRMW:
3181 case Instruction::CondBr:
3182 return !AssumedNoUBInsts.count(I);
3183 default:
3184 return false;
3185 }
3186 return false;
3187 }
3188
3189 /// Emit an optimization remark explaining why \p I is known to cause UB,
3190 /// per \p Info, right before it is replaced with 'unreachable'.
3191 static void emitUBRemark(Attributor &A, Instruction *I, const UBInfo &Info) {
3192 auto Remark = [&](OptimizationRemark OR) {
3193 switch (Info.K) {
3194 case UBInfo::NullPtrAccess:
3195 case UBInfo::UndefPtrAccess: {
3196 return OR << "Memory access through a pointer known to be "
3197 << ore::NV("Pointer",
3198 getPointerOperand(I, /*AllowVolatile*/ true))
3199 << " is undefined behavior; replacing with 'unreachable'.";
3200 }
3201 case UBInfo::UndefBranchCondition:
3202 return OR << "Branch condition known to be "
3203 << ore::NV("Condition", cast<CondBrInst>(I)->getCondition())
3204 << " is undefined behavior; replacing with 'unreachable'.";
3205 case UBInfo::UndefReturnValue:
3206 case UBInfo::NullReturnViolatesNonNull:
3207 return OR << "Value returned known to be "
3208 << ore::NV("ReturnValue",
3209 cast<ReturnInst>(I)->getReturnValue())
3210 << " is undefined behavior; replacing with 'unreachable'.";
3211 case UBInfo::UndefCallArgument:
3212 case UBInfo::NullArgViolatesNonNull: {
3213 bool IsUndef = Info.K == UBInfo::UndefCallArgument;
3214 CallBase &CB = *cast<CallBase>(I);
3215 OR << "Argument " << ore::NV("ArgNo", *Info.ArgNo)
3216 << " passed to parameter of ";
3217 if (auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand()))
3218 OR << ore::NV("Callee", Callee);
3219 else
3220 OR << "the callee";
3221 return OR << " known to be "
3222 << ore::NV("Argument", IsUndef ? "undef" : "null")
3223 << " is undefined behavior; replacing with 'unreachable'.";
3224 }
3225 }
3226 llvm_unreachable("Unknown UBInfo::Kind");
3227 };
3228 A.emitRemark<OptimizationRemark>(I, "UndefinedBehavior", Remark);
3229 }
3230
3231 ChangeStatus manifest(Attributor &A) override {
3232 if (KnownUBInsts.empty())
3233 return ChangeStatus::UNCHANGED;
3234 for (const auto &[I, Info] : KnownUBInsts) {
3235 emitUBRemark(A, I, Info);
3236 A.changeToUnreachableAfterManifest(I);
3237 }
3238 return ChangeStatus::CHANGED;
3239 }
3240
3241 /// See AbstractAttribute::getAsStr()
3242 const std::string getAsStr(Attributor *A) const override {
3243 return getAssumed() ? "undefined-behavior" : "no-ub";
3244 }
3245
3246 /// Note: The correctness of this analysis depends on the fact that the
3247 /// following 2 sets will stop changing after some point.
3248 /// "Change" here means that their size changes.
3249 /// The size of each set is monotonically increasing
3250 /// (we only add items to them) and it is upper bounded by the number of
3251 /// instructions in the processed function (we can never save more
3252 /// elements in either set than this number). Hence, at some point,
3253 /// they will stop increasing.
3254 /// Consequently, at some point, both sets will have stopped
3255 /// changing, effectively making the analysis reach a fixpoint.
3256
3257 /// Note: These 2 sets are disjoint and an instruction can be considered
3258 /// one of 3 things:
3259 /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
3260 /// the KnownUBInsts set.
3261 /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
3262 /// has a reason to assume it).
3263 /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
3264 /// could not find a reason to assume or prove that it can cause UB,
3265 /// hence it assumes it doesn't. We have a set for these instructions
3266 /// so that we don't reprocess them in every update.
3267 /// Note however that instructions in this set may cause UB.
3268
3269protected:
3270 /// A map from all live instructions _known_ to cause UB to the reason why,
3271 /// used to build actionable optimization remarks in manifest().
3272 MapVector<Instruction *, UBInfo> KnownUBInsts;
3273
3274private:
3275 /// A set of all the (live) instructions that are assumed to _not_ cause UB.
3276 SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;
3277
3278 // Should be called on updates in which if we're processing an instruction
3279 // \p I that depends on a value \p V, one of the following has to happen:
3280 // - If the value is assumed, then stop.
3281 // - If the value is known but undef, then consider it UB for \p K.
3282 // - Otherwise, do specific processing with the simplified value.
3283 // We return std::nullopt in the first 2 cases to signify that an appropriate
3284 // action was taken and the caller should stop.
3285 // Otherwise, we return the simplified value that the caller should
3286 // use for specific processing.
3287 std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
3288 Instruction *I, UBInfo::Kind K) {
3289 bool UsedAssumedInformation = false;
3290 std::optional<Value *> SimplifiedV =
3291 A.getAssumedSimplified(IRPosition::value(*V), *this,
3292 UsedAssumedInformation, AA::Interprocedural);
3293 if (!UsedAssumedInformation) {
3294 // Don't depend on assumed values.
3295 if (!SimplifiedV) {
3296 // If it is known (which we tested above) but it doesn't have a value,
3297 // then we can assume `undef` and hence the instruction is UB.
3298 KnownUBInsts.try_emplace(I, K);
3299 return std::nullopt;
3300 }
3301 if (!*SimplifiedV)
3302 return nullptr;
3303 V = *SimplifiedV;
3304 }
3305 if (isa<UndefValue>(V)) {
3306 KnownUBInsts.try_emplace(I, K);
3307 return std::nullopt;
3308 }
3309 return V;
3310 }
3311};
3312
3313struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
3314 AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
3315 : AAUndefinedBehaviorImpl(IRP, A) {}
3316
3317 /// See AbstractAttribute::trackStatistics()
3318 void trackStatistics() const override {
3319 STATS_DECL(UndefinedBehaviorInstruction, Instruction,
3320 "Number of instructions known to have UB");
3321 BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
3322 KnownUBInsts.size();
3323 }
3324};
3325} // namespace
3326
3327/// ------------------------ Will-Return Attributes ----------------------------
3328
3329namespace {
3330// Helper function that checks whether a function has any cycle which we don't
3331// know if it is bounded or not.
3332// Loops with maximum trip count are considered bounded, any other cycle not.
3333static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
3334 ScalarEvolution *SE =
3335 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
3336 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
3337 // If either SCEV or LoopInfo is not available for the function then we assume
3338 // any cycle to be unbounded cycle.
3339 // We use scc_iterator which uses Tarjan algorithm to find all the maximal
3340 // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
3341 if (!SE || !LI) {
3342 for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
3343 if (SCCI.hasCycle())
3344 return true;
3345 return false;
3346 }
3347
3348 // If there's irreducible control, the function may contain non-loop cycles.
3350 return true;
3351
3352 // Any loop that does not have a max trip count is considered unbounded cycle.
3353 for (auto *L : LI->getLoopsInPreorder()) {
3354 if (!SE->getSmallConstantMaxTripCount(L))
3355 return true;
3356 }
3357 return false;
3358}
3359
3360struct AAWillReturnImpl : public AAWillReturn {
3361 AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
3362 : AAWillReturn(IRP, A) {}
3363
3364 /// See AbstractAttribute::initialize(...).
3365 void initialize(Attributor &A) override {
3366 bool IsKnown;
3368 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
3369 (void)IsKnown;
3370 }
3371
3372 /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
3373 bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
3374 if (!A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
3375 return false;
3376
3377 bool IsKnown;
3378 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3379 return IsKnown || !KnownOnly;
3380 return false;
3381 }
3382
3383 /// See AbstractAttribute::updateImpl(...).
3384 ChangeStatus updateImpl(Attributor &A) override {
3385 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3386 return ChangeStatus::UNCHANGED;
3387
3388 auto CheckForWillReturn = [&](Instruction &I) {
3390 bool IsKnown;
3392 A, this, IPos, DepClassTy::REQUIRED, IsKnown)) {
3393 if (IsKnown)
3394 return true;
3395 } else {
3396 return false;
3397 }
3398 bool IsKnownNoRecurse;
3400 A, this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
3401 };
3402
3403 bool UsedAssumedInformation = false;
3404 if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
3405 UsedAssumedInformation))
3406 return indicatePessimisticFixpoint();
3407
3408 auto CheckForVolatile = [&](Instruction &I) {
3409 // Volatile operations are not willreturn.
3410 return !I.isVolatile();
3411 };
3412 if (!A.checkForAllInstructions(CheckForVolatile, *this,
3413 {Instruction::Load, Instruction::Store,
3414 Instruction::AtomicCmpXchg,
3415 Instruction::AtomicRMW},
3416 UsedAssumedInformation))
3417 return indicatePessimisticFixpoint();
3418
3419 return ChangeStatus::UNCHANGED;
3420 }
3421
3422 /// See AbstractAttribute::getAsStr()
3423 const std::string getAsStr(Attributor *A) const override {
3424 return getAssumed() ? "willreturn" : "may-noreturn";
3425 }
3426};
3427
3428struct AAWillReturnFunction final : AAWillReturnImpl {
3429 AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
3430 : AAWillReturnImpl(IRP, A) {}
3431
3432 /// See AbstractAttribute::initialize(...).
3433 void initialize(Attributor &A) override {
3434 AAWillReturnImpl::initialize(A);
3435
3436 Function *F = getAnchorScope();
3437 assert(F && "Did expect an anchor function");
3438 if (F->isDeclaration() || mayContainUnboundedCycle(*F, A))
3439 indicatePessimisticFixpoint();
3440 }
3441
3442 /// See AbstractAttribute::trackStatistics()
3443 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
3444};
3445
3446/// WillReturn attribute deduction for a call sites.
3447struct AAWillReturnCallSite final
3448 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {
3449 AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
3450 : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl>(IRP, A) {}
3451
3452 /// See AbstractAttribute::updateImpl(...).
3453 ChangeStatus updateImpl(Attributor &A) override {
3454 if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
3455 return ChangeStatus::UNCHANGED;
3456
3457 return AACalleeToCallSite::updateImpl(A);
3458 }
3459
3460 /// See AbstractAttribute::trackStatistics()
3461 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
3462};
3463} // namespace
3464
3465/// -------------------AAIntraFnReachability Attribute--------------------------
3466
3467/// All information associated with a reachability query. This boilerplate code
3468/// is used by both AAIntraFnReachability and AAInterFnReachability, with
3469/// different \p ToTy values.
3470template <typename ToTy> struct ReachabilityQueryInfo {
3471 enum class Reachable {
3474 };
3475
3476 /// Start here,
3477 const Instruction *From = nullptr;
3478 /// reach this place,
3479 const ToTy *To = nullptr;
3480 /// without going through any of these instructions,
3482 /// and remember if it worked:
3484
3485 /// Precomputed hash for this RQI.
3486 unsigned Hash = 0;
3487
3488 unsigned computeHashValue() const {
3489 assert(Hash == 0 && "Computed hash twice!");
3492 return const_cast<ReachabilityQueryInfo<ToTy> *>(this)->Hash =
3493 detail::combineHashValue(PairDMI ::getHashValue({From, To}),
3494 InstSetDMI::getHashValue(ExclusionSet));
3495 }
3496
3498 : From(From), To(To) {}
3499
3500 /// Constructor replacement to ensure unique and stable sets are used for the
3501 /// cache.
3503 const AA::InstExclusionSetTy *ES, bool MakeUnique)
3504 : From(&From), To(&To), ExclusionSet(ES) {
3505
3506 if (!ES || ES->empty()) {
3507 ExclusionSet = nullptr;
3508 } else if (MakeUnique) {
3509 ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
3510 }
3511 }
3512
3515};
3516
3517namespace llvm {
3518template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
3521
3522 static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
3523 return RQI->Hash ? RQI->Hash : RQI->computeHashValue();
3524 }
3525 static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
3526 const ReachabilityQueryInfo<ToTy> *RHS) {
3527 if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
3528 return false;
3529 return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
3530 }
3531};
3532
3533} // namespace llvm
3534
3535namespace {
3536
3537template <typename BaseTy, typename ToTy>
3538struct CachedReachabilityAA : public BaseTy {
3539 using RQITy = ReachabilityQueryInfo<ToTy>;
3540
3541 CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}
3542
3543 /// See AbstractAttribute::isQueryAA.
3544 bool isQueryAA() const override { return true; }
3545
3546 /// See AbstractAttribute::updateImpl(...).
3547 ChangeStatus updateImpl(Attributor &A) override {
3548 ChangeStatus Changed = ChangeStatus::UNCHANGED;
3549 for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
3550 RQITy *RQI = QueryVector[u];
3551 if (RQI->Result == RQITy::Reachable::No &&
3552 isReachableImpl(A, *RQI, /*IsTemporaryRQI=*/false))
3553 Changed = ChangeStatus::CHANGED;
3554 }
3555 return Changed;
3556 }
3557
3558 virtual bool isReachableImpl(Attributor &A, RQITy &RQI,
3559 bool IsTemporaryRQI) = 0;
3560
3561 bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
3562 RQITy &RQI, bool UsedExclusionSet, bool IsTemporaryRQI) {
3563 RQI.Result = Result;
3564
3565 // Remove the temporary RQI from the cache.
3566 if (IsTemporaryRQI)
3567 QueryCache.erase(&RQI);
3568
3569 // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
3570 // 1) If it is reachable, it doesn't matter if we have an exclusion set for
3571 // this query. 2) We did not use the exclusion set, potentially because
3572 // there is none.
3573 if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
3574 RQITy PlainRQI(RQI.From, RQI.To);
3575 if (!QueryCache.count(&PlainRQI)) {
3576 RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
3577 RQIPtr->Result = Result;
3578 QueryVector.push_back(RQIPtr);
3579 QueryCache.insert(RQIPtr);
3580 }
3581 }
3582
3583 // Check if we need to insert a new permanent RQI with the exclusion set.
3584 if (IsTemporaryRQI && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
3585 assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
3586 "Did not expect empty set!");
3587 RQITy *RQIPtr = new (A.Allocator)
3588 RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
3589 assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");
3590 RQIPtr->Result = Result;
3591 assert(!QueryCache.count(RQIPtr));
3592 QueryVector.push_back(RQIPtr);
3593 QueryCache.insert(RQIPtr);
3594 }
3595
3596 if (Result == RQITy::Reachable::No && IsTemporaryRQI)
3597 A.registerForUpdate(*this);
3598 return Result == RQITy::Reachable::Yes;
3599 }
3600
3601 const std::string getAsStr(Attributor *A) const override {
3602 // TODO: Return the number of reachable queries.
3603 return "#queries(" + std::to_string(QueryVector.size()) + ")";
3604 }
3605
3606 bool checkQueryCache(Attributor &A, RQITy &StackRQI,
3607 typename RQITy::Reachable &Result) {
3608 if (!this->getState().isValidState()) {
3609 Result = RQITy::Reachable::Yes;
3610 return true;
3611 }
3612
3613 // If we have an exclusion set we might be able to find our answer by
3614 // ignoring it first.
3615 if (StackRQI.ExclusionSet) {
3616 RQITy PlainRQI(StackRQI.From, StackRQI.To);
3617 auto It = QueryCache.find(&PlainRQI);
3618 if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
3619 Result = RQITy::Reachable::No;
3620 return true;
3621 }
3622 }
3623
3624 auto It = QueryCache.find(&StackRQI);
3625 if (It != QueryCache.end()) {
3626 Result = (*It)->Result;
3627 return true;
3628 }
3629
3630 // Insert a temporary for recursive queries. We will replace it with a
3631 // permanent entry later.
3632 QueryCache.insert(&StackRQI);
3633 return false;
3634 }
3635
3636private:
3637 SmallVector<RQITy *> QueryVector;
3638 DenseSet<RQITy *> QueryCache;
3639};
3640
3641struct AAIntraFnReachabilityFunction final
3642 : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
3643 using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
3644 AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
3645 : Base(IRP, A) {
3646 DT = A.getInfoCache().getAnalysisResultForFunction<DominatorTreeAnalysis>(
3647 *IRP.getAssociatedFunction());
3648 }
3649
3650 bool isAssumedReachable(
3651 Attributor &A, const Instruction &From, const Instruction &To,
3652 const AA::InstExclusionSetTy *ExclusionSet) const override {
3653 auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
3654 if (&From == &To)
3655 return true;
3656
3657 RQITy StackRQI(A, From, To, ExclusionSet, false);
3658 RQITy::Reachable Result;
3659 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
3660 return NonConstThis->isReachableImpl(A, StackRQI,
3661 /*IsTemporaryRQI=*/true);
3662 return Result == RQITy::Reachable::Yes;
3663 }
3664
3665 ChangeStatus updateImpl(Attributor &A) override {
3666 // We only depend on liveness. DeadEdges is all we care about, check if any
3667 // of them changed.
3668 auto *LivenessAA =
3669 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3670 if (LivenessAA &&
3671 llvm::all_of(DeadEdges,
3672 [&](const auto &DeadEdge) {
3673 return LivenessAA->isEdgeDead(DeadEdge.first,
3674 DeadEdge.second);
3675 }) &&
3676 llvm::all_of(DeadBlocks, [&](const BasicBlock *BB) {
3677 return LivenessAA->isAssumedDead(BB);
3678 })) {
3679 return ChangeStatus::UNCHANGED;
3680 }
3681 DeadEdges.clear();
3682 DeadBlocks.clear();
3683 return Base::updateImpl(A);
3684 }
3685
3686 bool isReachableImpl(Attributor &A, RQITy &RQI,
3687 bool IsTemporaryRQI) override {
3688 const Instruction *Origin = RQI.From;
3689 bool UsedExclusionSet = false;
3690
3691 auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
3692 const AA::InstExclusionSetTy *ExclusionSet) {
3693 const Instruction *IP = &From;
3694 while (IP && IP != &To) {
3695 if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {
3696 UsedExclusionSet = true;
3697 break;
3698 }
3699 IP = IP->getNextNode();
3700 }
3701 return IP == &To;
3702 };
3703
3704 const BasicBlock *FromBB = RQI.From->getParent();
3705 const BasicBlock *ToBB = RQI.To->getParent();
3706 assert(FromBB->getParent() == ToBB->getParent() &&
3707 "Not an intra-procedural query!");
3708
3709 // Check intra-block reachability, however, other reaching paths are still
3710 // possible.
3711 if (FromBB == ToBB &&
3712 WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
3713 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3714 IsTemporaryRQI);
3715
3716 // Check if reaching the ToBB block is sufficient or if even that would not
3717 // ensure reaching the target. In the latter case we are done.
3718 if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
3719 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3720 IsTemporaryRQI);
3721
3722 const Function *Fn = FromBB->getParent();
3723 SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
3724 if (RQI.ExclusionSet)
3725 for (auto *I : *RQI.ExclusionSet)
3726 if (I->getFunction() == Fn)
3727 ExclusionBlocks.insert(I->getParent());
3728
3729 // Check if we make it out of the FromBB block at all.
3730 if (ExclusionBlocks.count(FromBB) &&
3731 !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
3732 RQI.ExclusionSet))
3733 return rememberResult(A, RQITy::Reachable::No, RQI, true, IsTemporaryRQI);
3734
3735 auto *LivenessAA =
3736 A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
3737 if (LivenessAA && LivenessAA->isAssumedDead(ToBB)) {
3738 DeadBlocks.insert(ToBB);
3739 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3740 IsTemporaryRQI);
3741 }
3742
3743 SmallPtrSet<const BasicBlock *, 16> Visited;
3745 Worklist.push_back(FromBB);
3746
3747 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
3748 while (!Worklist.empty()) {
3749 const BasicBlock *BB = Worklist.pop_back_val();
3750 if (!Visited.insert(BB).second)
3751 continue;
3752 for (const BasicBlock *SuccBB : successors(BB)) {
3753 if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
3754 LocalDeadEdges.insert({BB, SuccBB});
3755 continue;
3756 }
3757 // We checked before if we just need to reach the ToBB block.
3758 if (SuccBB == ToBB)
3759 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3760 IsTemporaryRQI);
3761 if (DT && ExclusionBlocks.empty() && DT->dominates(BB, ToBB))
3762 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
3763 IsTemporaryRQI);
3764
3765 if (ExclusionBlocks.count(SuccBB)) {
3766 UsedExclusionSet = true;
3767 continue;
3768 }
3769 Worklist.push_back(SuccBB);
3770 }
3771 }
3772
3773 DeadEdges.insert_range(LocalDeadEdges);
3774 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
3775 IsTemporaryRQI);
3776 }
3777
3778 /// See AbstractAttribute::trackStatistics()
3779 void trackStatistics() const override {}
3780
3781private:
3782 // Set of assumed dead blocks we used in the last query. If any changes we
3783 // update the state.
3784 DenseSet<const BasicBlock *> DeadBlocks;
3785
3786 // Set of assumed dead edges we used in the last query. If any changes we
3787 // update the state.
3788 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
3789
3790 /// The dominator tree of the function to short-circuit reasoning.
3791 const DominatorTree *DT = nullptr;
3792};
3793} // namespace
3794
3795/// ------------------------ NoAlias Argument Attribute ------------------------
3796
3798 Attribute::AttrKind ImpliedAttributeKind,
3799 bool IgnoreSubsumingPositions) {
3800 assert(ImpliedAttributeKind == Attribute::NoAlias &&
3801 "Unexpected attribute kind");
3802 Value *Val = &IRP.getAssociatedValue();
3804 if (isa<AllocaInst>(Val))
3805 return true;
3806 } else {
3807 IgnoreSubsumingPositions = true;
3808 }
3809
3810 if (isa<UndefValue>(Val))
3811 return true;
3812
3813 if (isa<ConstantPointerNull>(Val) &&
3816 return true;
3817
3818 if (A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
3819 IgnoreSubsumingPositions, Attribute::NoAlias))
3820 return true;
3821
3822 return false;
3823}
3824
3825namespace {
3826struct AANoAliasImpl : AANoAlias {
3827 AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
3828 assert(getAssociatedType()->isPointerTy() &&
3829 "Noalias is a pointer attribute");
3830 }
3831
3832 const std::string getAsStr(Attributor *A) const override {
3833 return getAssumed() ? "noalias" : "may-alias";
3834 }
3835};
3836
3837/// NoAlias attribute for a floating value.
3838struct AANoAliasFloating final : AANoAliasImpl {
3839 AANoAliasFloating(const IRPosition &IRP, Attributor &A)
3840 : AANoAliasImpl(IRP, A) {}
3841
3842 /// See AbstractAttribute::updateImpl(...).
3843 ChangeStatus updateImpl(Attributor &A) override {
3844 // TODO: Implement this.
3845 return indicatePessimisticFixpoint();
3846 }
3847
3848 /// See AbstractAttribute::trackStatistics()
3849 void trackStatistics() const override {
3851 }
3852};
3853
3854/// NoAlias attribute for an argument.
3855struct AANoAliasArgument final
3856 : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {
3857 using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl>;
3858 AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
3859
3860 /// See AbstractAttribute::update(...).
3861 ChangeStatus updateImpl(Attributor &A) override {
3862 // We have to make sure no-alias on the argument does not break
3863 // synchronization when this is a callback argument, see also [1] below.
3864 // If synchronization cannot be affected, we delegate to the base updateImpl
3865 // function, otherwise we give up for now.
3866
3867 // If the function is no-sync, no-alias cannot break synchronization.
3868 bool IsKnownNoSycn;
3870 A, this, IRPosition::function_scope(getIRPosition()),
3871 DepClassTy::OPTIONAL, IsKnownNoSycn))
3872 return Base::updateImpl(A);
3873
3874 // If the argument is read-only, no-alias cannot break synchronization.
3875 bool IsKnown;
3876 if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
3877 return Base::updateImpl(A);
3878
3879 // If the argument is never passed through callbacks, no-alias cannot break
3880 // synchronization.
3881 bool UsedAssumedInformation = false;
3882 if (A.checkForAllCallSites(
3883 [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
3884 true, UsedAssumedInformation))
3885 return Base::updateImpl(A);
3886
3887 // TODO: add no-alias but make sure it doesn't break synchronization by
3888 // introducing fake uses. See:
3889 // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
3890 // International Workshop on OpenMP 2018,
3891 // http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf
3892
3893 return indicatePessimisticFixpoint();
3894 }
3895
3896 /// See AbstractAttribute::trackStatistics()
3897 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
3898};
3899
3900struct AANoAliasCallSiteArgument final : AANoAliasImpl {
3901 AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
3902 : AANoAliasImpl(IRP, A) {}
3903
3904 /// Determine if the underlying value may alias with the call site argument
3905 /// \p OtherArgNo of \p ICS (= the underlying call site).
3906 bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
3907 const AAMemoryBehavior &MemBehaviorAA,
3908 const CallBase &CB, unsigned OtherArgNo) {
3909 // We do not need to worry about aliasing with the underlying IRP.
3910 if (this->getCallSiteArgNo() == (int)OtherArgNo)
3911 return false;
3912
3913 // If it is not a pointer or pointer vector we do not alias.
3914 const Value *ArgOp = CB.getArgOperand(OtherArgNo);
3915 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
3916 return false;
3917
3918 auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
3919 *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);
3920
3921 // If the argument is readnone, there is no read-write aliasing.
3922 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
3923 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3924 return false;
3925 }
3926
3927 // If the argument is readonly and the underlying value is readonly, there
3928 // is no read-write aliasing.
3929 bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
3930 if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
3931 IsReadOnly) {
3932 A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
3933 A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
3934 return false;
3935 }
3936
3937 // We have to utilize actual alias analysis queries so we need the object.
3938 if (!AAR)
3939 AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(
3940 *getAnchorScope());
3941
3942 // Try to rule it out at the call site.
3943 bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
3944 LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
3945 "callsite arguments: "
3946 << getAssociatedValue() << " " << *ArgOp << " => "
3947 << (IsAliasing ? "" : "no-") << "alias \n");
3948
3949 return IsAliasing;
3950 }
3951
3952 bool isKnownNoAliasDueToNoAliasPreservation(
3953 Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {
3954 // We can deduce "noalias" if the following conditions hold.
3955 // (i) Associated value is assumed to be noalias in the definition.
3956 // (ii) Associated value is assumed to be no-capture in all the uses
3957 // possibly executed before this callsite.
3958 // (iii) There is no other pointer argument which could alias with the
3959 // value.
3960
3961 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
3962 const Function *ScopeFn = VIRP.getAnchorScope();
3963 // Check whether the value is captured in the scope using AANoCapture.
3964 // Look at CFG and check only uses possibly executed before this
3965 // callsite.
3966 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
3967 Instruction *UserI = cast<Instruction>(U.getUser());
3968
3969 // If UserI is the curr instruction and there is a single potential use of
3970 // the value in UserI we allow the use.
3971 // TODO: We should inspect the operands and allow those that cannot alias
3972 // with the value.
3973 if (UserI == getCtxI() && UserI->getNumOperands() == 1)
3974 return true;
3975
3976 if (ScopeFn) {
3977 if (auto *CB = dyn_cast<CallBase>(UserI)) {
3978 if (CB->isArgOperand(&U)) {
3979
3980 unsigned ArgNo = CB->getArgOperandNo(&U);
3981
3982 bool IsKnownNoCapture;
3984 A, this, IRPosition::callsite_argument(*CB, ArgNo),
3985 DepClassTy::OPTIONAL, IsKnownNoCapture))
3986 return true;
3987 }
3988 }
3989
3991 A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
3992 [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
3993 return true;
3994 }
3995
3996 // TODO: We should track the capturing uses in AANoCapture but the problem
3997 // is CGSCC runs. For those we would need to "allow" AANoCapture for
3998 // a value in the module slice.
3999 // TODO(captures): Make this more precise.
4000 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
4001 if (capturesNothing(CI))
4002 return true;
4003 if (CI.isPassthrough()) {
4004 Follow = true;
4005 return true;
4006 }
4007 LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI << "\n");
4008 return false;
4009 };
4010
4011 bool IsKnownNoCapture;
4012 const AANoCapture *NoCaptureAA = nullptr;
4013 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
4014 A, this, VIRP, DepClassTy::NONE, IsKnownNoCapture, false, &NoCaptureAA);
4015 if (!IsAssumedNoCapture &&
4016 (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
4017 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
4018 LLVM_DEBUG(
4019 dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
4020 << " cannot be noalias as it is potentially captured\n");
4021 return false;
4022 }
4023 }
4024 if (NoCaptureAA)
4025 A.recordDependence(*NoCaptureAA, *this, DepClassTy::OPTIONAL);
4026
4027 // Check there is no other pointer argument which could alias with the
4028 // value passed at this call site.
4029 // TODO: AbstractCallSite
4030 const auto &CB = cast<CallBase>(getAnchorValue());
4031 for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
4032 if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
4033 return false;
4034
4035 return true;
4036 }
4037
4038 /// See AbstractAttribute::updateImpl(...).
4039 ChangeStatus updateImpl(Attributor &A) override {
4040 // If the argument is readnone we are done as there are no accesses via the
4041 // argument.
4042 auto *MemBehaviorAA =
4043 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
4044 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
4045 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
4046 return ChangeStatus::UNCHANGED;
4047 }
4048
4049 bool IsKnownNoAlias;
4050 const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
4052 A, this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
4053 LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
4054 << " is not no-alias at the definition\n");
4055 return indicatePessimisticFixpoint();
4056 }
4057
4058 AAResults *AAR = nullptr;
4059 if (MemBehaviorAA &&
4060 isKnownNoAliasDueToNoAliasPreservation(A, AAR, *MemBehaviorAA)) {
4061 LLVM_DEBUG(
4062 dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
4063 return ChangeStatus::UNCHANGED;
4064 }
4065
4066 return indicatePessimisticFixpoint();
4067 }
4068
4069 /// See AbstractAttribute::trackStatistics()
4070 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
4071};
4072
4073/// NoAlias attribute for function return value.
4074struct AANoAliasReturned final : AANoAliasImpl {
4075 AANoAliasReturned(const IRPosition &IRP, Attributor &A)
4076 : AANoAliasImpl(IRP, A) {}
4077
4078 /// See AbstractAttribute::updateImpl(...).
4079 ChangeStatus updateImpl(Attributor &A) override {
4080
4081 auto CheckReturnValue = [&](Value &RV) -> bool {
4082 if (Constant *C = dyn_cast<Constant>(&RV))
4083 if (C->isNullValue() || isa<UndefValue>(C))
4084 return true;
4085
4086 /// For now, we can only deduce noalias if we have call sites.
4087 /// FIXME: add more support.
4088 if (!isa<CallBase>(&RV))
4089 return false;
4090
4091 const IRPosition &RVPos = IRPosition::value(RV);
4092 bool IsKnownNoAlias;
4094 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
4095 return false;
4096
4097 bool IsKnownNoCapture;
4098 const AANoCapture *NoCaptureAA = nullptr;
4099 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
4100 A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
4101 &NoCaptureAA);
4102 return IsAssumedNoCapture ||
4103 (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());
4104 };
4105
4106 if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
4107 return indicatePessimisticFixpoint();
4108
4109 return ChangeStatus::UNCHANGED;
4110 }
4111
4112 /// See AbstractAttribute::trackStatistics()
4113 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
4114};
4115
4116/// NoAlias attribute deduction for a call site return value.
4117struct AANoAliasCallSiteReturned final
4118 : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {
4119 AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
4120 : AACalleeToCallSite<AANoAlias, AANoAliasImpl>(IRP, A) {}
4121
4122 /// See AbstractAttribute::trackStatistics()
4123 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
4124};
4125} // namespace
4126
4127/// -------------------AAIsDead Function Attribute-----------------------
4128
4129namespace {
4130struct AAIsDeadValueImpl : public AAIsDead {
4131 AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4132
4133 /// See AAIsDead::isAssumedDead().
4134 bool isAssumedDead() const override { return isAssumed(IS_DEAD); }
4135
4136 /// See AAIsDead::isKnownDead().
4137 bool isKnownDead() const override { return isKnown(IS_DEAD); }
4138
4139 /// See AAIsDead::isAssumedDead(BasicBlock *).
4140 bool isAssumedDead(const BasicBlock *BB) const override { return false; }
4141
4142 /// See AAIsDead::isKnownDead(BasicBlock *).
4143 bool isKnownDead(const BasicBlock *BB) const override { return false; }
4144
4145 /// See AAIsDead::isAssumedDead(Instruction *I).
4146 bool isAssumedDead(const Instruction *I) const override {
4147 return I == getCtxI() && isAssumedDead();
4148 }
4149
4150 /// See AAIsDead::isKnownDead(Instruction *I).
4151 bool isKnownDead(const Instruction *I) const override {
4152 return isAssumedDead(I) && isKnownDead();
4153 }
4154
4155 /// See AbstractAttribute::getAsStr().
4156 const std::string getAsStr(Attributor *A) const override {
4157 return isAssumedDead() ? "assumed-dead" : "assumed-live";
4158 }
4159
4160 /// Check if all uses are assumed dead.
4161 bool areAllUsesAssumedDead(Attributor &A, Value &V) {
4162 // Callers might not check the type, void has no uses.
4163 if (V.getType()->isVoidTy() || V.use_empty())
4164 return true;
4165
4166 // If we replace a value with a constant there are no uses left afterwards.
4167 if (!isa<Constant>(V)) {
4168 if (auto *I = dyn_cast<Instruction>(&V))
4169 if (!A.isRunOn(*I->getFunction()))
4170 return false;
4171 bool UsedAssumedInformation = false;
4172 std::optional<Constant *> C =
4173 A.getAssumedConstant(V, *this, UsedAssumedInformation);
4174 if (!C || *C)
4175 return true;
4176 }
4177
4178 auto UsePred = [&](const Use &U, bool &Follow) { return false; };
4179 // Explicitly set the dependence class to required because we want a long
4180 // chain of N dependent instructions to be considered live as soon as one is
4181 // without going through N update cycles. This is not required for
4182 // correctness.
4183 return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
4184 DepClassTy::REQUIRED,
4185 /* IgnoreDroppableUses */ false);
4186 }
4187
4188 /// Determine if \p I is assumed to be side-effect free.
4189 bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
4191 return true;
4192
4193 if (!I->isTerminator() && !I->mayHaveSideEffects())
4194 return true;
4195
4196 auto *CB = dyn_cast<CallBase>(I);
4197 if (!CB || isa<IntrinsicInst>(CB))
4198 return false;
4199
4200 const IRPosition &CallIRP = IRPosition::callsite_function(*CB);
4201
4202 bool IsKnownNoUnwind;
4204 A, this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
4205 return false;
4206
4207 bool IsKnown;
4208 return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
4209 }
4210};
4211
4212struct AAIsDeadFloating : public AAIsDeadValueImpl {
4213 AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
4214 : AAIsDeadValueImpl(IRP, A) {}
4215
4216 /// See AbstractAttribute::initialize(...).
4217 void initialize(Attributor &A) override {
4218 AAIsDeadValueImpl::initialize(A);
4219
4220 if (isa<UndefValue>(getAssociatedValue())) {
4221 indicatePessimisticFixpoint();
4222 return;
4223 }
4224
4225 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4226 if (!isAssumedSideEffectFree(A, I)) {
4228 indicatePessimisticFixpoint();
4229 else
4230 removeAssumedBits(HAS_NO_EFFECT);
4231 }
4232 }
4233
4234 bool isDeadFence(Attributor &A, FenceInst &FI) {
4235 const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
4236 IRPosition::function(*FI.getFunction()), *this, DepClassTy::NONE);
4237 if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
4238 return false;
4239 A.recordDependence(*ExecDomainAA, *this, DepClassTy::OPTIONAL);
4240 return true;
4241 }
4242
4243 bool isDeadStore(Attributor &A, StoreInst &SI,
4244 SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
4245 // Lang ref now states volatile store is not UB/dead, let's skip them.
4246 if (SI.isVolatile())
4247 return false;
4248
4249 // If we are collecting assumes to be deleted we are in the manifest stage.
4250 // It's problematic to collect the potential copies again now so we use the
4251 // cached ones.
4252 bool UsedAssumedInformation = false;
4253 if (!AssumeOnlyInst) {
4254 PotentialCopies.clear();
4255 if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
4256 UsedAssumedInformation)) {
4257 LLVM_DEBUG(
4258 dbgs()
4259 << "[AAIsDead] Could not determine potential copies of store!\n");
4260 return false;
4261 }
4262 }
4263 LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
4264 << " potential copies.\n");
4265
4266 InformationCache &InfoCache = A.getInfoCache();
4267 return llvm::all_of(PotentialCopies, [&](Value *V) {
4268 if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
4269 UsedAssumedInformation))
4270 return true;
4271 if (auto *LI = dyn_cast<LoadInst>(V)) {
4272 if (llvm::all_of(LI->uses(), [&](const Use &U) {
4273 auto &UserI = cast<Instruction>(*U.getUser());
4274 if (InfoCache.isOnlyUsedByAssume(UserI)) {
4275 if (AssumeOnlyInst)
4276 AssumeOnlyInst->insert(&UserI);
4277 return true;
4278 }
4279 return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
4280 })) {
4281 return true;
4282 }
4283 }
4284 LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
4285 << " is assumed live!\n");
4286 return false;
4287 });
4288 }
4289
4290 /// See AbstractAttribute::getAsStr().
4291 const std::string getAsStr(Attributor *A) const override {
4292 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4294 if (isValidState())
4295 return "assumed-dead-store";
4297 if (isValidState())
4298 return "assumed-dead-fence";
4299 return AAIsDeadValueImpl::getAsStr(A);
4300 }
4301
4302 /// See AbstractAttribute::updateImpl(...).
4303 ChangeStatus updateImpl(Attributor &A) override {
4304 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
4305 if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
4306 if (!isDeadStore(A, *SI))
4307 return indicatePessimisticFixpoint();
4308 } else if (auto *FI = dyn_cast_or_null<FenceInst>(I)) {
4309 if (!isDeadFence(A, *FI))
4310 return indicatePessimisticFixpoint();
4311 } else {
4312 if (!isAssumedSideEffectFree(A, I))
4313 return indicatePessimisticFixpoint();
4314 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4315 return indicatePessimisticFixpoint();
4316 }
4318 }
4319
4320 bool isRemovableStore() const override {
4321 return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
4322 }
4323
4324 /// See AbstractAttribute::manifest(...).
4325 ChangeStatus manifest(Attributor &A) override {
4326 Value &V = getAssociatedValue();
4327 if (auto *I = dyn_cast<Instruction>(&V)) {
4328 // If we get here we basically know the users are all dead. We check if
4329 // isAssumedSideEffectFree returns true here again because it might not be
4330 // the case and only the users are dead but the instruction (=call) is
4331 // still needed.
4332 if (auto *SI = dyn_cast<StoreInst>(I)) {
4333 SmallSetVector<Instruction *, 8> AssumeOnlyInst;
4334 bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
4335 (void)IsDead;
4336 assert(IsDead && "Store was assumed to be dead!");
4337 A.deleteAfterManifest(*I);
4338 for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
4339 Instruction *AOI = AssumeOnlyInst[i];
4340 for (auto *Usr : AOI->users())
4341 AssumeOnlyInst.insert(cast<Instruction>(Usr));
4342 A.deleteAfterManifest(*AOI);
4343 }
4344 return ChangeStatus::CHANGED;
4345 }
4346 if (auto *FI = dyn_cast<FenceInst>(I)) {
4347 assert(isDeadFence(A, *FI));
4348 A.deleteAfterManifest(*FI);
4349 return ChangeStatus::CHANGED;
4350 }
4351 if (isAssumedSideEffectFree(A, I) && !I->isTerminator()) {
4352 A.deleteAfterManifest(*I);
4353 return ChangeStatus::CHANGED;
4354 }
4355 }
4357 }
4358
4359 /// See AbstractAttribute::trackStatistics()
4360 void trackStatistics() const override {
4362 }
4363
4364private:
4365 // The potential copies of a dead store, used for deletion during manifest.
4366 SmallSetVector<Value *, 4> PotentialCopies;
4367};
4368
4369struct AAIsDeadArgument : public AAIsDeadFloating {
4370 AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
4371 : AAIsDeadFloating(IRP, A) {}
4372
4373 /// See AbstractAttribute::manifest(...).
4374 ChangeStatus manifest(Attributor &A) override {
4375 Argument &Arg = *getAssociatedArgument();
4376 if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
4377 if (A.registerFunctionSignatureRewrite(
4378 Arg, /* ReplacementTypes */ {},
4381 return ChangeStatus::CHANGED;
4382 }
4383 return ChangeStatus::UNCHANGED;
4384 }
4385
4386 /// See AbstractAttribute::trackStatistics()
4387 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
4388};
4389
4390struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
4391 AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
4392 : AAIsDeadValueImpl(IRP, A) {}
4393
4394 /// See AbstractAttribute::initialize(...).
4395 void initialize(Attributor &A) override {
4396 AAIsDeadValueImpl::initialize(A);
4397 if (isa<UndefValue>(getAssociatedValue()))
4398 indicatePessimisticFixpoint();
4399 }
4400
4401 /// See AbstractAttribute::updateImpl(...).
4402 ChangeStatus updateImpl(Attributor &A) override {
4403 // TODO: Once we have call site specific value information we can provide
4404 // call site specific liveness information and then it makes
4405 // sense to specialize attributes for call sites arguments instead of
4406 // redirecting requests to the callee argument.
4407 Argument *Arg = getAssociatedArgument();
4408 if (!Arg)
4409 return indicatePessimisticFixpoint();
4410 const IRPosition &ArgPos = IRPosition::argument(*Arg);
4411 auto *ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
4412 if (!ArgAA)
4413 return indicatePessimisticFixpoint();
4414 return clampStateAndIndicateChange(getState(), ArgAA->getState());
4415 }
4416
4417 /// See AbstractAttribute::manifest(...).
4418 ChangeStatus manifest(Attributor &A) override {
4419 CallBase &CB = cast<CallBase>(getAnchorValue());
4420 Use &U = CB.getArgOperandUse(getCallSiteArgNo());
4421 assert(!isa<UndefValue>(U.get()) &&
4422 "Expected undef values to be filtered out!");
4423 UndefValue &UV = *UndefValue::get(U->getType());
4424 if (A.changeUseAfterManifest(U, UV))
4425 return ChangeStatus::CHANGED;
4426 return ChangeStatus::UNCHANGED;
4427 }
4428
4429 /// See AbstractAttribute::trackStatistics()
4430 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
4431};
4432
4433struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
4434 AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
4435 : AAIsDeadFloating(IRP, A) {}
4436
4437 /// See AAIsDead::isAssumedDead().
4438 bool isAssumedDead() const override {
4439 return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
4440 }
4441
4442 /// See AbstractAttribute::initialize(...).
4443 void initialize(Attributor &A) override {
4444 AAIsDeadFloating::initialize(A);
4445 if (isa<UndefValue>(getAssociatedValue())) {
4446 indicatePessimisticFixpoint();
4447 return;
4448 }
4449
4450 // We track this separately as a secondary state.
4451 IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
4452 }
4453
4454 /// See AbstractAttribute::updateImpl(...).
4455 ChangeStatus updateImpl(Attributor &A) override {
4456 ChangeStatus Changed = ChangeStatus::UNCHANGED;
4457 if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
4458 IsAssumedSideEffectFree = false;
4459 Changed = ChangeStatus::CHANGED;
4460 }
4461 if (!areAllUsesAssumedDead(A, getAssociatedValue()))
4462 return indicatePessimisticFixpoint();
4463 return Changed;
4464 }
4465
4466 /// See AbstractAttribute::trackStatistics()
4467 void trackStatistics() const override {
4468 if (IsAssumedSideEffectFree)
4470 else
4471 STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
4472 }
4473
4474 /// See AbstractAttribute::getAsStr().
4475 const std::string getAsStr(Attributor *A) const override {
4476 return isAssumedDead()
4477 ? "assumed-dead"
4478 : (getAssumed() ? "assumed-dead-users" : "assumed-live");
4479 }
4480
4481private:
4482 bool IsAssumedSideEffectFree = true;
4483};
4484
4485struct AAIsDeadReturned : public AAIsDeadValueImpl {
4486 AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
4487 : AAIsDeadValueImpl(IRP, A) {}
4488
4489 /// See AbstractAttribute::updateImpl(...).
4490 ChangeStatus updateImpl(Attributor &A) override {
4491
4492 bool UsedAssumedInformation = false;
4493 A.checkForAllInstructions([](Instruction &) { return true; }, *this,
4494 {Instruction::Ret}, UsedAssumedInformation);
4495
4496 auto PredForCallSite = [&](AbstractCallSite ACS) {
4497 if (ACS.isCallbackCall() || !ACS.getInstruction())
4498 return false;
4499 return areAllUsesAssumedDead(A, *ACS.getInstruction());
4500 };
4501
4502 if (!A.checkForAllCallSites(PredForCallSite, *this, true,
4503 UsedAssumedInformation))
4504 return indicatePessimisticFixpoint();
4505
4506 return ChangeStatus::UNCHANGED;
4507 }
4508
4509 /// See AbstractAttribute::manifest(...).
4510 ChangeStatus manifest(Attributor &A) override {
4511 // TODO: Rewrite the signature to return void?
4512 bool AnyChange = false;
4513 UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
4514 auto RetInstPred = [&](Instruction &I) {
4515 ReturnInst &RI = cast<ReturnInst>(I);
4517 AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
4518 return true;
4519 };
4520 bool UsedAssumedInformation = false;
4521 A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
4522 UsedAssumedInformation);
4523 return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
4524 }
4525
4526 /// See AbstractAttribute::trackStatistics()
4527 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
4528};
4529
4530struct AAIsDeadFunction : public AAIsDead {
4531 AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}
4532
4533 /// See AbstractAttribute::initialize(...).
4534 void initialize(Attributor &A) override {
4535 Function *F = getAnchorScope();
4536 assert(F && "Did expect an anchor function");
4537 if (!isAssumedDeadInternalFunction(A)) {
4538 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4539 assumeLive(A, F->getEntryBlock());
4540 }
4541 }
4542
4543 bool isAssumedDeadInternalFunction(Attributor &A) {
4544 if (!getAnchorScope()->hasLocalLinkage())
4545 return false;
4546 // An AA that will not be updated is fixed pessimistically right after
4547 // initialization, so an assumed-dead result would be discarded. Checking
4548 // the call sites recursively initializes the liveness of every internal
4549 // caller, which in CGSCC cleanup repeats for each callee SCC.
4550 if (!A.shouldUpdateAA<AAIsDead>(getIRPosition()))
4551 return false;
4552 bool UsedAssumedInformation = false;
4553 return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
4554 true, UsedAssumedInformation);
4555 }
4556
4557 /// See AbstractAttribute::getAsStr().
4558 const std::string getAsStr(Attributor *A) const override {
4559 return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
4560 std::to_string(getAnchorScope()->size()) + "][#TBEP " +
4561 std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
4562 std::to_string(KnownDeadEnds.size()) + "]";
4563 }
4564
4565 /// See AbstractAttribute::manifest(...).
4566 ChangeStatus manifest(Attributor &A) override {
4567 assert(getState().isValidState() &&
4568 "Attempted to manifest an invalid state!");
4569
4570 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
4571 Function &F = *getAnchorScope();
4572
4573 if (AssumedLiveBlocks.empty()) {
4574 A.deleteAfterManifest(F);
4575 return ChangeStatus::CHANGED;
4576 }
4577
4578 // Flag to determine if we can change an invoke to a call assuming the
4579 // callee is nounwind. This is not possible if the personality of the
4580 // function allows to catch asynchronous exceptions.
4581 bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);
4582
4583 KnownDeadEnds.set_union(ToBeExploredFrom);
4584 for (const Instruction *DeadEndI : KnownDeadEnds) {
4585 auto *CB = dyn_cast<CallBase>(DeadEndI);
4586 if (!CB)
4587 continue;
4588 bool IsKnownNoReturn;
4590 A, this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL,
4591 IsKnownNoReturn);
4592 if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
4593 continue;
4594
4595 if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
4596 A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
4597 else
4598 A.changeToUnreachableAfterManifest(
4599 const_cast<Instruction *>(DeadEndI->getNextNode()));
4600 HasChanged = ChangeStatus::CHANGED;
4601 }
4602
4603 STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
4604 for (BasicBlock &BB : F)
4605 if (!AssumedLiveBlocks.count(&BB)) {
4606 A.deleteAfterManifest(BB);
4607 ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
4608 HasChanged = ChangeStatus::CHANGED;
4609 }
4610
4611 return HasChanged;
4612 }
4613
4614 /// See AbstractAttribute::updateImpl(...).
4615 ChangeStatus updateImpl(Attributor &A) override;
4616
4617 bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
4618 assert(From->getParent() == getAnchorScope() &&
4619 To->getParent() == getAnchorScope() &&
4620 "Used AAIsDead of the wrong function");
4621 return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
4622 }
4623
4624 /// See AbstractAttribute::trackStatistics()
4625 void trackStatistics() const override {}
4626
4627 /// Returns true if the function is assumed dead.
4628 bool isAssumedDead() const override { return false; }
4629
4630 /// See AAIsDead::isKnownDead().
4631 bool isKnownDead() const override { return false; }
4632
4633 /// See AAIsDead::isAssumedDead(BasicBlock *).
4634 bool isAssumedDead(const BasicBlock *BB) const override {
4635 assert(BB->getParent() == getAnchorScope() &&
4636 "BB must be in the same anchor scope function.");
4637
4638 if (!getAssumed())
4639 return false;
4640 return !AssumedLiveBlocks.count(BB);
4641 }
4642
4643 /// See AAIsDead::isKnownDead(BasicBlock *).
4644 bool isKnownDead(const BasicBlock *BB) const override {
4645 return getKnown() && isAssumedDead(BB);
4646 }
4647
4648 /// See AAIsDead::isAssumed(Instruction *I).
4649 bool isAssumedDead(const Instruction *I) const override {
4650 assert(I->getParent()->getParent() == getAnchorScope() &&
4651 "Instruction must be in the same anchor scope function.");
4652
4653 if (!getAssumed())
4654 return false;
4655
4656 // If it is not in AssumedLiveBlocks then it for sure dead.
4657 // Otherwise, it can still be after noreturn call in a live block.
4658 if (!AssumedLiveBlocks.count(I->getParent()))
4659 return true;
4660
4661 // If it is not after a liveness barrier it is live.
4662 const Instruction *PrevI = I->getPrevNode();
4663 while (PrevI) {
4664 if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
4665 return true;
4666 PrevI = PrevI->getPrevNode();
4667 }
4668 return false;
4669 }
4670
4671 /// See AAIsDead::isKnownDead(Instruction *I).
4672 bool isKnownDead(const Instruction *I) const override {
4673 return getKnown() && isAssumedDead(I);
4674 }
4675
4676 /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
4677 /// that internal function called from \p BB should now be looked at.
4678 bool assumeLive(Attributor &A, const BasicBlock &BB) {
4679 if (!AssumedLiveBlocks.insert(&BB).second)
4680 return false;
4681
4682 if (!A.isDuringDeduction())
4683 return true;
4684
4685 // We assume that all of BB is (probably) live now and if there are calls to
4686 // internal functions we will assume that those are now live as well. This
4687 // is a performance optimization for blocks with calls to a lot of internal
4688 // functions. It can however cause dead functions to be treated as live.
4689 for (const Instruction &I : BB)
4690 if (const auto *CB = dyn_cast<CallBase>(&I))
4692 if (F->hasLocalLinkage()) {
4693 LLVM_DEBUG({
4694 dbgs() << "[AAIsDead] Seeding live internal callee ";
4695 F->printAsOperand(dbgs(), /*PrintType=*/false);
4696 dbgs() << " from ";
4697 BB.getParent()->printAsOperand(dbgs(), /*PrintType=*/false);
4698 dbgs() << "\n";
4699 });
4700 A.markLiveInternalFunction(*F);
4701 }
4702 return true;
4703 }
4704
4705 /// Collection of instructions that need to be explored again, e.g., we
4706 /// did assume they do not transfer control to (one of their) successors.
4707 SmallSetVector<const Instruction *, 8> ToBeExploredFrom;
4708
4709 /// Collection of instructions that are known to not transfer control.
4710 SmallSetVector<const Instruction *, 8> KnownDeadEnds;
4711
4712 /// Collection of all assumed live edges
4713 DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;
4714
4715 /// Collection of all assumed live BasicBlocks.
4716 DenseSet<const BasicBlock *> AssumedLiveBlocks;
4717};
4718
4719static bool
4720identifyAliveSuccessors(Attributor &A, const CallBase &CB,
4721 AbstractAttribute &AA,
4722 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4723 const IRPosition &IPos = IRPosition::callsite_function(CB);
4724
4725 bool IsKnownNoReturn;
4727 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoReturn))
4728 return !IsKnownNoReturn;
4729 if (CB.isTerminator())
4730 AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
4731 else
4732 AliveSuccessors.push_back(CB.getNextNode());
4733 return false;
4734}
4735
4736static bool
4737identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
4738 AbstractAttribute &AA,
4739 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4740 bool UsedAssumedInformation =
4741 identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);
4742
4743 // First, determine if we can change an invoke to a call assuming the
4744 // callee is nounwind. This is not possible if the personality of the
4745 // function allows to catch asynchronous exceptions.
4746 if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
4747 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4748 } else {
4749 const IRPosition &IPos = IRPosition::callsite_function(II);
4750
4751 bool IsKnownNoUnwind;
4753 A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
4754 UsedAssumedInformation |= !IsKnownNoUnwind;
4755 } else {
4756 AliveSuccessors.push_back(&II.getUnwindDest()->front());
4757 }
4758 }
4759 return UsedAssumedInformation;
4760}
4761
4762static bool
4763identifyAliveSuccessors(Attributor &, const UncondBrInst &BI,
4764 AbstractAttribute &,
4765 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4766 AliveSuccessors.push_back(&BI.getSuccessor()->front());
4767 return false;
4768}
4769
4770static bool
4771identifyAliveSuccessors(Attributor &A, const CondBrInst &BI,
4772 AbstractAttribute &AA,
4773 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4774 bool UsedAssumedInformation = false;
4775 std::optional<Constant *> C =
4776 A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
4777 if (!C || isa_and_nonnull<UndefValue>(*C)) {
4778 // No value yet, assume both edges are dead.
4779 } else if (isa_and_nonnull<ConstantInt>(*C)) {
4780 const BasicBlock *SuccBB =
4781 BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
4782 AliveSuccessors.push_back(&SuccBB->front());
4783 } else {
4784 AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
4785 AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
4786 UsedAssumedInformation = false;
4787 }
4788 return UsedAssumedInformation;
4789}
4790
4791static bool
4792identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
4793 AbstractAttribute &AA,
4794 SmallVectorImpl<const Instruction *> &AliveSuccessors) {
4795 bool UsedAssumedInformation = false;
4797 if (!A.getAssumedSimplifiedValues(IRPosition::value(*SI.getCondition()), &AA,
4799 UsedAssumedInformation)) {
4800 // Something went wrong, assume all successors are live.
4801 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4802 AliveSuccessors.push_back(&SuccBB->front());
4803 return false;
4804 }
4805
4806 if (Values.empty() ||
4807 (Values.size() == 1 &&
4808 isa_and_nonnull<UndefValue>(Values.front().getValue()))) {
4809 // No valid value yet, assume all edges are dead.
4810 return UsedAssumedInformation;
4811 }
4812
4813 Type &Ty = *SI.getCondition()->getType();
4814 SmallPtrSet<ConstantInt *, 8> Constants;
4815 auto CheckForConstantInt = [&](Value *V) {
4816 if (auto *CI = dyn_cast_if_present<ConstantInt>(AA::getWithType(*V, Ty))) {
4817 Constants.insert(CI);
4818 return true;
4819 }
4820 return false;
4821 };
4822
4823 if (!all_of(Values, [&](AA::ValueAndContext &VAC) {
4824 return CheckForConstantInt(VAC.getValue());
4825 })) {
4826 for (const BasicBlock *SuccBB : successors(SI.getParent()))
4827 AliveSuccessors.push_back(&SuccBB->front());
4828 return UsedAssumedInformation;
4829 }
4830
4831 unsigned MatchedCases = 0;
4832 for (const auto &CaseIt : SI.cases()) {
4833 if (Constants.count(CaseIt.getCaseValue())) {
4834 ++MatchedCases;
4835 AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
4836 }
4837 }
4838
4839 // If all potential values have been matched, we will not visit the default
4840 // case.
4841 if (MatchedCases < Constants.size())
4842 AliveSuccessors.push_back(&SI.getDefaultDest()->front());
4843 return UsedAssumedInformation;
4844}
4845
4846ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
4848
4849 if (AssumedLiveBlocks.empty()) {
4850 if (isAssumedDeadInternalFunction(A))
4852
4853 Function *F = getAnchorScope();
4854 ToBeExploredFrom.insert(&F->getEntryBlock().front());
4855 assumeLive(A, F->getEntryBlock());
4856 Change = ChangeStatus::CHANGED;
4857 }
4858
4859 LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
4860 << getAnchorScope()->size() << "] BBs and "
4861 << ToBeExploredFrom.size() << " exploration points and "
4862 << KnownDeadEnds.size() << " known dead ends\n");
4863
4864 // Copy and clear the list of instructions we need to explore from. It is
4865 // refilled with instructions the next update has to look at.
4866 SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
4867 ToBeExploredFrom.end());
4868 decltype(ToBeExploredFrom) NewToBeExploredFrom;
4869
4871 while (!Worklist.empty()) {
4872 const Instruction *I = Worklist.pop_back_val();
4873 LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");
4874
4875 // Fast forward for uninteresting instructions. We could look for UB here
4876 // though.
4877 while (!I->isTerminator() && !isa<CallBase>(I))
4878 I = I->getNextNode();
4879
4880 AliveSuccessors.clear();
4881
4882 bool UsedAssumedInformation = false;
4883 switch (I->getOpcode()) {
4884 // TODO: look for (assumed) UB to backwards propagate "deadness".
4885 default:
4886 assert(I->isTerminator() &&
4887 "Expected non-terminators to be handled already!");
4888 for (const BasicBlock *SuccBB : successors(I->getParent()))
4889 AliveSuccessors.push_back(&SuccBB->front());
4890 break;
4891 case Instruction::Call:
4892 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
4893 *this, AliveSuccessors);
4894 break;
4895 case Instruction::Invoke:
4896 UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
4897 *this, AliveSuccessors);
4898 break;
4899 case Instruction::UncondBr:
4900 UsedAssumedInformation = identifyAliveSuccessors(
4901 A, cast<UncondBrInst>(*I), *this, AliveSuccessors);
4902 break;
4903 case Instruction::CondBr:
4904 UsedAssumedInformation = identifyAliveSuccessors(A, cast<CondBrInst>(*I),
4905 *this, AliveSuccessors);
4906 break;
4907 case Instruction::Switch:
4908 UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
4909 *this, AliveSuccessors);
4910 break;
4911 }
4912
4913 if (UsedAssumedInformation) {
4914 NewToBeExploredFrom.insert(I);
4915 } else if (AliveSuccessors.empty() ||
4916 (I->isTerminator() &&
4917 AliveSuccessors.size() < I->getNumSuccessors())) {
4918 if (KnownDeadEnds.insert(I))
4919 Change = ChangeStatus::CHANGED;
4920 }
4921
4922 LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
4923 << AliveSuccessors.size() << " UsedAssumedInformation: "
4924 << UsedAssumedInformation << "\n");
4925
4926 for (const Instruction *AliveSuccessor : AliveSuccessors) {
4927 if (!I->isTerminator()) {
4928 assert(AliveSuccessors.size() == 1 &&
4929 "Non-terminator expected to have a single successor!");
4930 Worklist.push_back(AliveSuccessor);
4931 } else {
4932 // record the assumed live edge
4933 auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
4934 if (AssumedLiveEdges.insert(Edge).second)
4935 Change = ChangeStatus::CHANGED;
4936 if (assumeLive(A, *AliveSuccessor->getParent()))
4937 Worklist.push_back(AliveSuccessor);
4938 }
4939 }
4940 }
4941
4942 // Check if the content of ToBeExploredFrom changed, ignore the order.
4943 if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
4944 llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
4945 return !ToBeExploredFrom.count(I);
4946 })) {
4947 Change = ChangeStatus::CHANGED;
4948 ToBeExploredFrom = std::move(NewToBeExploredFrom);
4949 }
4950
4951 // If we know everything is live there is no need to query for liveness.
4952 // Instead, indicating a pessimistic fixpoint will cause the state to be
4953 // "invalid" and all queries to be answered conservatively without lookups.
4954 // To be in this state we have to (1) finished the exploration and (3) not
4955 // discovered any non-trivial dead end and (2) not ruled unreachable code
4956 // dead.
4957 if (ToBeExploredFrom.empty() &&
4958 getAnchorScope()->size() == AssumedLiveBlocks.size() &&
4959 llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
4960 return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
4961 }))
4962 return indicatePessimisticFixpoint();
4963 return Change;
4964}
4965
4966/// Liveness information for a call sites.
4967struct AAIsDeadCallSite final : AAIsDeadFunction {
4968 AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
4969 : AAIsDeadFunction(IRP, A) {}
4970
4971 /// See AbstractAttribute::initialize(...).
4972 void initialize(Attributor &A) override {
4973 // TODO: Once we have call site specific value information we can provide
4974 // call site specific liveness information and then it makes
4975 // sense to specialize attributes for call sites instead of
4976 // redirecting requests to the callee.
4977 llvm_unreachable("Abstract attributes for liveness are not "
4978 "supported for call sites yet!");
4979 }
4980
4981 /// See AbstractAttribute::updateImpl(...).
4982 ChangeStatus updateImpl(Attributor &A) override {
4983 return indicatePessimisticFixpoint();
4984 }
4985
4986 /// See AbstractAttribute::trackStatistics()
4987 void trackStatistics() const override {}
4988};
4989} // namespace
4990
4991/// -------------------- Dereferenceable Argument Attribute --------------------
4992
4993namespace {
4994struct AADereferenceableImpl : AADereferenceable {
4995 AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
4996 : AADereferenceable(IRP, A) {}
4997 using StateType = DerefState;
4998
4999 /// See AbstractAttribute::initialize(...).
5000 void initialize(Attributor &A) override {
5001 Value &V = *getAssociatedValue().stripPointerCasts();
5003 A.getAttrs(getIRPosition(),
5004 {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
5005 Attrs, /* IgnoreSubsumingPositions */ false);
5006 for (const Attribute &Attr : Attrs)
5007 takeKnownDerefBytesMaximum(Attr.getValueAsInt());
5008
5009 // Ensure we initialize the non-null AA (if necessary).
5010 bool IsKnownNonNull;
5012 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);
5013
5014 bool CanBeNull;
5015 takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
5016 A.getDataLayout(), CanBeNull, /*CanBeFreed=*/nullptr));
5017
5018 if (Instruction *CtxI = getCtxI())
5019 followUsesInMBEC(*this, A, getState(), *CtxI);
5020 }
5021
5022 /// See AbstractAttribute::getState()
5023 /// {
5024 StateType &getState() override { return *this; }
5025 const StateType &getState() const override { return *this; }
5026 /// }
5027
5028 /// Helper function for collecting accessed bytes in must-be-executed-context
5029 void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
5030 DerefState &State) {
5031 const Value *UseV = U->get();
5032 if (!UseV->getType()->isPointerTy())
5033 return;
5034
5035 std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
5036 if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
5037 return;
5038
5039 int64_t Offset;
5041 Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
5042 if (Base && Base == &getAssociatedValue())
5043 State.addAccessedBytes(Offset, Loc->Size.getValue());
5044 }
5045
5046 /// See followUsesInMBEC
5047 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5048 AADereferenceable::StateType &State) {
5049 bool IsNonNull = false;
5050 bool TrackUse = false;
5051 int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
5052 A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
5053 LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
5054 << " for instruction " << *I << "\n");
5055
5056 addAccessedBytesForUse(A, U, I, State);
5057 State.takeKnownDerefBytesMaximum(DerefBytes);
5058 return TrackUse;
5059 }
5060
5061 /// See AbstractAttribute::manifest(...).
5062 ChangeStatus manifest(Attributor &A) override {
5063 ChangeStatus Change = AADereferenceable::manifest(A);
5064 bool IsKnownNonNull;
5065 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5066 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5067 if (IsAssumedNonNull &&
5068 A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
5069 A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
5070 return ChangeStatus::CHANGED;
5071 }
5072 return Change;
5073 }
5074
5075 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5076 SmallVectorImpl<Attribute> &Attrs) const override {
5077 // TODO: Add *_globally support
5078 bool IsKnownNonNull;
5079 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
5080 A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5081 if (IsAssumedNonNull)
5082 Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
5083 Ctx, getAssumedDereferenceableBytes()));
5084 else
5085 Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
5086 Ctx, getAssumedDereferenceableBytes()));
5087 }
5088
5089 /// See AbstractAttribute::getAsStr().
5090 const std::string getAsStr(Attributor *A) const override {
5091 if (!getAssumedDereferenceableBytes())
5092 return "unknown-dereferenceable";
5093 bool IsKnownNonNull;
5094 bool IsAssumedNonNull = false;
5095 if (A)
5097 *A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
5098 return std::string("dereferenceable") +
5099 (IsAssumedNonNull ? "" : "_or_null") +
5100 (isAssumedGlobal() ? "_globally" : "") + "<" +
5101 std::to_string(getKnownDereferenceableBytes()) + "-" +
5102 std::to_string(getAssumedDereferenceableBytes()) + ">" +
5103 (!A ? " [non-null is unknown]" : "");
5104 }
5105};
5106
5107/// Dereferenceable attribute for a floating value.
5108struct AADereferenceableFloating : AADereferenceableImpl {
5109 AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
5110 : AADereferenceableImpl(IRP, A) {}
5111
5112 /// See AbstractAttribute::updateImpl(...).
5113 ChangeStatus updateImpl(Attributor &A) override {
5114 bool Stripped;
5115 bool UsedAssumedInformation = false;
5117 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5118 AA::AnyScope, UsedAssumedInformation)) {
5119 Values.push_back({getAssociatedValue(), getCtxI()});
5120 Stripped = false;
5121 } else {
5122 Stripped = Values.size() != 1 ||
5123 Values.front().getValue() != &getAssociatedValue();
5124 }
5125
5126 const DataLayout &DL = A.getDataLayout();
5127 DerefState T;
5128
5129 auto VisitValueCB = [&](const Value &V) -> bool {
5130 unsigned IdxWidth =
5131 DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
5132 APInt Offset(IdxWidth, 0);
5134 A, *this, &V, DL, Offset, /* GetMinOffset */ false,
5135 /* AllowNonInbounds */ true);
5136
5137 const auto *AA = A.getAAFor<AADereferenceable>(
5138 *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
5139 int64_t DerefBytes = 0;
5140 if (!AA || (!Stripped && this == AA)) {
5141 // Use IR information if we did not strip anything.
5142 // TODO: track globally.
5143 bool CanBeNull;
5144 DerefBytes = Base->getPointerDereferenceableBytes(
5145 DL, CanBeNull, /*CanBeFreed=*/nullptr);
5146 T.GlobalState.indicatePessimisticFixpoint();
5147 } else {
5148 const DerefState &DS = AA->getState();
5149 DerefBytes = DS.DerefBytesState.getAssumed();
5150 T.GlobalState &= DS.GlobalState;
5151 }
5152
5153 // For now we do not try to "increase" dereferenceability due to negative
5154 // indices as we first have to come up with code to deal with loops and
5155 // for overflows of the dereferenceable bytes.
5156 int64_t OffsetSExt = Offset.getSExtValue();
5157 if (OffsetSExt < 0)
5158 OffsetSExt = 0;
5159
5160 T.takeAssumedDerefBytesMinimum(
5161 std::max(int64_t(0), DerefBytes - OffsetSExt));
5162
5163 if (this == AA) {
5164 if (!Stripped) {
5165 // If nothing was stripped IR information is all we got.
5166 T.takeKnownDerefBytesMaximum(
5167 std::max(int64_t(0), DerefBytes - OffsetSExt));
5168 T.indicatePessimisticFixpoint();
5169 } else if (OffsetSExt > 0) {
5170 // If something was stripped but there is circular reasoning we look
5171 // for the offset. If it is positive we basically decrease the
5172 // dereferenceable bytes in a circular loop now, which will simply
5173 // drive them down to the known value in a very slow way which we
5174 // can accelerate.
5175 T.indicatePessimisticFixpoint();
5176 }
5177 }
5178
5179 return T.isValidState();
5180 };
5181
5182 for (const auto &VAC : Values)
5183 if (!VisitValueCB(*VAC.getValue()))
5184 return indicatePessimisticFixpoint();
5185
5186 return clampStateAndIndicateChange(getState(), T);
5187 }
5188
5189 /// See AbstractAttribute::trackStatistics()
5190 void trackStatistics() const override {
5191 STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
5192 }
5193};
5194
5195/// Dereferenceable attribute for a return value.
5196struct AADereferenceableReturned final
5197 : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
5198 using Base =
5199 AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
5200 AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
5201 : Base(IRP, A) {}
5202
5203 /// See AbstractAttribute::trackStatistics()
5204 void trackStatistics() const override {
5205 STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
5206 }
5207};
5208
5209/// Dereferenceable attribute for an argument
5210struct AADereferenceableArgument final
5211 : AAArgumentFromCallSiteArguments<AADereferenceable,
5212 AADereferenceableImpl> {
5213 using Base =
5214 AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
5215 AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
5216 : Base(IRP, A) {}
5217
5218 /// See AbstractAttribute::trackStatistics()
5219 void trackStatistics() const override {
5220 STATS_DECLTRACK_ARG_ATTR(dereferenceable)
5221 }
5222};
5223
5224/// Dereferenceable attribute for a call site argument.
5225struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
5226 AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
5227 : AADereferenceableFloating(IRP, A) {}
5228
5229 /// See AbstractAttribute::trackStatistics()
5230 void trackStatistics() const override {
5231 STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
5232 }
5233};
5234
5235/// Dereferenceable attribute deduction for a call site return value.
5236struct AADereferenceableCallSiteReturned final
5237 : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {
5238 using Base = AACalleeToCallSite<AADereferenceable, AADereferenceableImpl>;
5239 AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
5240 : Base(IRP, A) {}
5241
5242 /// See AbstractAttribute::trackStatistics()
5243 void trackStatistics() const override {
5244 STATS_DECLTRACK_CS_ATTR(dereferenceable);
5245 }
5246};
5247} // namespace
5248
5249// ------------------------ Align Argument Attribute ------------------------
5250
5251namespace {
5252
5253static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
5254 Value &AssociatedValue, const Use *U,
5255 const Instruction *I, bool &TrackUse) {
5256 // We need to follow common pointer manipulation uses to the accesses they
5257 // feed into.
5258 if (isa<CastInst>(I)) {
5259 // Follow all but ptr2int casts.
5260 TrackUse = !isa<PtrToIntInst>(I);
5261 return 0;
5262 }
5263 if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
5264 if (GEP->hasAllConstantIndices())
5265 TrackUse = true;
5266 return 0;
5267 }
5268 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I))
5269 switch (II->getIntrinsicID()) {
5270 case Intrinsic::ptrmask: {
5271 // Is it appropriate to pull attribute in initialization?
5272 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5273 QueryingAA, IRPosition::value(*II->getOperand(1)), DepClassTy::NONE);
5274 const auto *AlignAA = A.getAAFor<AAAlign>(
5275 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5276 if (ConstVals && ConstVals->isValidState() && ConstVals->isAtFixpoint()) {
5277 unsigned ShiftValue = std::min(ConstVals->getAssumedMinTrailingZeros(),
5279 Align ConstAlign = Align::fromLog2(ShiftValue);
5280 if (ConstAlign >= AlignAA->getKnownAlign())
5281 return Align(1).value();
5282 }
5283 if (AlignAA)
5284 return AlignAA->getKnownAlign().value();
5285 break;
5286 }
5287 case Intrinsic::amdgcn_make_buffer_rsrc: {
5288 const auto *AlignAA = A.getAAFor<AAAlign>(
5289 QueryingAA, IRPosition::value(*II), DepClassTy::NONE);
5290 if (AlignAA)
5291 return AlignAA->getKnownAlign().value();
5292 break;
5293 }
5294 default:
5295 break;
5296 }
5297
5298 MaybeAlign MA;
5299 if (const auto *CB = dyn_cast<CallBase>(I)) {
5300 if (CB->isBundleOperand(U) || CB->isCallee(U))
5301 return 0;
5302
5303 unsigned ArgNo = CB->getArgOperandNo(U);
5304 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
5305 // As long as we only use known information there is no need to track
5306 // dependences here.
5307 auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
5308 if (AlignAA)
5309 MA = MaybeAlign(AlignAA->getKnownAlign());
5310 }
5311
5312 const DataLayout &DL = A.getDataLayout();
5313 const Value *UseV = U->get();
5314 if (auto *SI = dyn_cast<StoreInst>(I)) {
5315 if (SI->getPointerOperand() == UseV)
5316 MA = SI->getAlign();
5317 } else if (auto *LI = dyn_cast<LoadInst>(I)) {
5318 if (LI->getPointerOperand() == UseV)
5319 MA = LI->getAlign();
5320 } else if (auto *AI = dyn_cast<AtomicRMWInst>(I)) {
5321 if (AI->getPointerOperand() == UseV)
5322 MA = AI->getAlign();
5323 } else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
5324 if (AI->getPointerOperand() == UseV)
5325 MA = AI->getAlign();
5326 }
5327
5328 if (!MA || *MA <= QueryingAA.getKnownAlign())
5329 return 0;
5330
5331 unsigned Alignment = MA->value();
5332 int64_t Offset;
5333
5334 if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
5335 if (Base == &AssociatedValue) {
5336 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5337 // So we can say that the maximum power of two which is a divisor of
5338 // gcd(Offset, Alignment) is an alignment.
5339
5340 uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
5342 }
5343 }
5344
5345 return Alignment;
5346}
5347
5348struct AAAlignImpl : AAAlign {
5349 AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}
5350
5351 /// See AbstractAttribute::initialize(...).
5352 void initialize(Attributor &A) override {
5354 A.getAttrs(getIRPosition(), {Attribute::Alignment}, Attrs);
5355 for (const Attribute &Attr : Attrs)
5356 takeKnownMaximum(Attr.getValueAsInt());
5357
5358 Value &V = *getAssociatedValue().stripPointerCasts();
5359 takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());
5360
5361 if (Instruction *CtxI = getCtxI())
5362 followUsesInMBEC(*this, A, getState(), *CtxI);
5363 }
5364
5365 /// See AbstractAttribute::manifest(...).
5366 ChangeStatus manifest(Attributor &A) override {
5367 ChangeStatus InstrChanged = ChangeStatus::UNCHANGED;
5368
5369 // Check for users that allow alignment annotations.
5370 Value &AssociatedValue = getAssociatedValue();
5371 if (isa<ConstantData>(AssociatedValue))
5372 return ChangeStatus::UNCHANGED;
5373
5374 for (const Use &U : AssociatedValue.uses()) {
5375 if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
5376 if (SI->getPointerOperand() == &AssociatedValue)
5377 if (SI->getAlign() < getAssumedAlign()) {
5378 STATS_DECLTRACK(AAAlign, Store,
5379 "Number of times alignment added to a store");
5380 SI->setAlignment(getAssumedAlign());
5381 InstrChanged = ChangeStatus::CHANGED;
5382 }
5383 } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
5384 if (LI->getPointerOperand() == &AssociatedValue)
5385 if (LI->getAlign() < getAssumedAlign()) {
5386 LI->setAlignment(getAssumedAlign());
5387 STATS_DECLTRACK(AAAlign, Load,
5388 "Number of times alignment added to a load");
5389 InstrChanged = ChangeStatus::CHANGED;
5390 }
5391 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(U.getUser())) {
5392 if (RMW->getPointerOperand() == &AssociatedValue) {
5393 if (RMW->getAlign() < getAssumedAlign()) {
5394 STATS_DECLTRACK(AAAlign, AtomicRMW,
5395 "Number of times alignment added to atomicrmw");
5396
5397 RMW->setAlignment(getAssumedAlign());
5398 InstrChanged = ChangeStatus::CHANGED;
5399 }
5400 }
5401 } else if (auto *CAS = dyn_cast<AtomicCmpXchgInst>(U.getUser())) {
5402 if (CAS->getPointerOperand() == &AssociatedValue) {
5403 if (CAS->getAlign() < getAssumedAlign()) {
5404 STATS_DECLTRACK(AAAlign, AtomicCmpXchg,
5405 "Number of times alignment added to cmpxchg");
5406 CAS->setAlignment(getAssumedAlign());
5407 InstrChanged = ChangeStatus::CHANGED;
5408 }
5409 }
5410 }
5411 }
5412
5413 ChangeStatus Changed = AAAlign::manifest(A);
5414
5415 Align InheritAlign =
5416 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5417 if (InheritAlign >= getAssumedAlign())
5418 return InstrChanged;
5419 return Changed | InstrChanged;
5420 }
5421
5422 // TODO: Provide a helper to determine the implied ABI alignment and check in
5423 // the existing manifest method and a new one for AAAlignImpl that value
5424 // to avoid making the alignment explicit if it did not improve.
5425
5426 /// See AbstractAttribute::getDeducedAttributes
5427 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
5428 SmallVectorImpl<Attribute> &Attrs) const override {
5429 if (getAssumedAlign() > 1)
5430 Attrs.emplace_back(
5431 Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
5432 }
5433
5434 /// See followUsesInMBEC
5435 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
5436 AAAlign::StateType &State) {
5437 bool TrackUse = false;
5438
5439 unsigned int KnownAlign =
5440 getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
5441 State.takeKnownMaximum(KnownAlign);
5442
5443 return TrackUse;
5444 }
5445
5446 /// See AbstractAttribute::getAsStr().
5447 const std::string getAsStr(Attributor *A) const override {
5448 return "align<" + std::to_string(getKnownAlign().value()) + "-" +
5449 std::to_string(getAssumedAlign().value()) + ">";
5450 }
5451};
5452
5453/// Align attribute for a floating value.
5454struct AAAlignFloating : AAAlignImpl {
5455 AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}
5456
5457 /// See AbstractAttribute::updateImpl(...).
5458 ChangeStatus updateImpl(Attributor &A) override {
5459 const DataLayout &DL = A.getDataLayout();
5460
5461 bool Stripped;
5462 bool UsedAssumedInformation = false;
5464 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
5465 AA::AnyScope, UsedAssumedInformation)) {
5466 Values.push_back({getAssociatedValue(), getCtxI()});
5467 Stripped = false;
5468 } else {
5469 Stripped = Values.size() != 1 ||
5470 Values.front().getValue() != &getAssociatedValue();
5471 }
5472
5473 StateType T;
5474 auto VisitValueCB = [&](Value &V) -> bool {
5476 return true;
5477 const auto *AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
5478 DepClassTy::REQUIRED);
5479 if (!AA || (!Stripped && this == AA)) {
5480 int64_t Offset;
5481 unsigned Alignment = 1;
5482 if (const Value *Base =
5484 // TODO: Use AAAlign for the base too.
5485 Align PA = Base->getPointerAlignment(DL);
5486 // BasePointerAddr + Offset = Alignment * Q for some integer Q.
5487 // So we can say that the maximum power of two which is a divisor of
5488 // gcd(Offset, Alignment) is an alignment.
5489
5490 uint32_t gcd =
5491 std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
5493 } else {
5494 Alignment = V.getPointerAlignment(DL).value();
5495 }
5496 // Use only IR information if we did not strip anything.
5497 T.takeKnownMaximum(Alignment);
5498 T.indicatePessimisticFixpoint();
5499 } else {
5500 // Use abstract attribute information.
5501 const AAAlign::StateType &DS = AA->getState();
5502 T ^= DS;
5503 }
5504 return T.isValidState();
5505 };
5506
5507 for (const auto &VAC : Values) {
5508 if (!VisitValueCB(*VAC.getValue()))
5509 return indicatePessimisticFixpoint();
5510 }
5511
5512 // TODO: If we know we visited all incoming values, thus no are assumed
5513 // dead, we can take the known information from the state T.
5514 return clampStateAndIndicateChange(getState(), T);
5515 }
5516
5517 /// See AbstractAttribute::trackStatistics()
5518 void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
5519};
5520
5521/// Align attribute for function return value.
5522struct AAAlignReturned final
5523 : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
5524 using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
5525 AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5526
5527 /// See AbstractAttribute::trackStatistics()
5528 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
5529};
5530
5531/// Align attribute for function argument.
5532struct AAAlignArgument final
5533 : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
5534 using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
5535 AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}
5536
5537 /// See AbstractAttribute::manifest(...).
5538 ChangeStatus manifest(Attributor &A) override {
5539 // If the associated argument is involved in a must-tail call we give up
5540 // because we would need to keep the argument alignments of caller and
5541 // callee in-sync. Just does not seem worth the trouble right now.
5542 if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
5543 return ChangeStatus::UNCHANGED;
5544 return Base::manifest(A);
5545 }
5546
5547 /// See AbstractAttribute::trackStatistics()
5548 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
5549};
5550
5551struct AAAlignCallSiteArgument final : AAAlignFloating {
5552 AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
5553 : AAAlignFloating(IRP, A) {}
5554
5555 /// See AbstractAttribute::manifest(...).
5556 ChangeStatus manifest(Attributor &A) override {
5557 // If the associated argument is involved in a must-tail call we give up
5558 // because we would need to keep the argument alignments of caller and
5559 // callee in-sync. Just does not seem worth the trouble right now.
5560 if (Argument *Arg = getAssociatedArgument())
5561 if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
5562 return ChangeStatus::UNCHANGED;
5563 ChangeStatus Changed = AAAlignImpl::manifest(A);
5564 Align InheritAlign =
5565 getAssociatedValue().getPointerAlignment(A.getDataLayout());
5566 if (InheritAlign >= getAssumedAlign())
5567 Changed = ChangeStatus::UNCHANGED;
5568 return Changed;
5569 }
5570
5571 /// See AbstractAttribute::updateImpl(Attributor &A).
5572 ChangeStatus updateImpl(Attributor &A) override {
5573 ChangeStatus Changed = AAAlignFloating::updateImpl(A);
5574 if (Argument *Arg = getAssociatedArgument()) {
5575 // We only take known information from the argument
5576 // so we do not need to track a dependence.
5577 const auto *ArgAlignAA = A.getAAFor<AAAlign>(
5578 *this, IRPosition::argument(*Arg), DepClassTy::NONE);
5579 if (ArgAlignAA)
5580 takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
5581 }
5582 return Changed;
5583 }
5584
5585 /// See AbstractAttribute::trackStatistics()
5586 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
5587};
5588
5589/// Align attribute deduction for a call site return value.
5590struct AAAlignCallSiteReturned final
5591 : AACalleeToCallSite<AAAlign, AAAlignImpl> {
5592 using Base = AACalleeToCallSite<AAAlign, AAAlignImpl>;
5593 AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
5594 : Base(IRP, A) {}
5595
5596 ChangeStatus updateImpl(Attributor &A) override {
5597 Instruction *I = getIRPosition().getCtxI();
5598 if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
5599 switch (II->getIntrinsicID()) {
5600 case Intrinsic::ptrmask: {
5602 bool Valid = false;
5603
5604 const auto *ConstVals = A.getAAFor<AAPotentialConstantValues>(
5605 *this, IRPosition::value(*II->getOperand(1)), DepClassTy::REQUIRED);
5606 if (ConstVals && ConstVals->isValidState()) {
5607 unsigned ShiftValue =
5608 std::min(ConstVals->getAssumedMinTrailingZeros(),
5609 Value::MaxAlignmentExponent);
5610 Alignment = Align::fromLog2(ShiftValue);
5611 Valid = true;
5612 }
5613
5614 const auto *AlignAA =
5615 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5616 DepClassTy::REQUIRED);
5617 if (AlignAA) {
5618 Alignment = std::max(AlignAA->getAssumedAlign(), Alignment);
5619 Valid = true;
5620 }
5621
5622 if (Valid)
5624 this->getState(),
5625 std::min(this->getAssumedAlign(), Alignment).value());
5626 break;
5627 }
5628 // FIXME: Should introduce target specific sub-attributes and letting
5629 // getAAfor<AAAlign> lead to create sub-attribute to handle target
5630 // specific intrinsics.
5631 case Intrinsic::amdgcn_make_buffer_rsrc: {
5632 const auto *AlignAA =
5633 A.getAAFor<AAAlign>(*this, IRPosition::value(*(II->getOperand(0))),
5634 DepClassTy::REQUIRED);
5635 if (AlignAA)
5637 this->getState(), AlignAA->getAssumedAlign().value());
5638 break;
5639 }
5640 default:
5641 break;
5642 }
5643 }
5644 return Base::updateImpl(A);
5645 };
5646 /// See AbstractAttribute::trackStatistics()
5647 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
5648};
5649} // namespace
5650
5651/// ------------------ Function No-Return Attribute ----------------------------
5652namespace {
5653struct AANoReturnImpl : public AANoReturn {
5654 AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}
5655
5656 /// See AbstractAttribute::initialize(...).
5657 void initialize(Attributor &A) override {
5658 bool IsKnown;
5660 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5661 (void)IsKnown;
5662 }
5663
5664 /// See AbstractAttribute::getAsStr().
5665 const std::string getAsStr(Attributor *A) const override {
5666 return getAssumed() ? "noreturn" : "may-return";
5667 }
5668
5669 /// See AbstractAttribute::updateImpl(Attributor &A).
5670 ChangeStatus updateImpl(Attributor &A) override {
5671 auto CheckForNoReturn = [](Instruction &) { return false; };
5672 bool UsedAssumedInformation = false;
5673 if (!A.checkForAllInstructions(CheckForNoReturn, *this,
5674 {(unsigned)Instruction::Ret},
5675 UsedAssumedInformation))
5676 return indicatePessimisticFixpoint();
5677 return ChangeStatus::UNCHANGED;
5678 }
5679};
5680
5681struct AANoReturnFunction final : AANoReturnImpl {
5682 AANoReturnFunction(const IRPosition &IRP, Attributor &A)
5683 : AANoReturnImpl(IRP, A) {}
5684
5685 /// See AbstractAttribute::trackStatistics()
5686 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
5687};
5688
5689/// NoReturn attribute deduction for a call sites.
5690struct AANoReturnCallSite final
5691 : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {
5692 AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
5693 : AACalleeToCallSite<AANoReturn, AANoReturnImpl>(IRP, A) {}
5694
5695 /// See AbstractAttribute::trackStatistics()
5696 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
5697};
5698} // namespace
5699
5700/// ----------------------- Instance Info ---------------------------------
5701
5702namespace {
5703/// A class to hold the state of for no-capture attributes.
5704struct AAInstanceInfoImpl : public AAInstanceInfo {
5705 AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
5706 : AAInstanceInfo(IRP, A) {}
5707
5708 /// See AbstractAttribute::initialize(...).
5709 void initialize(Attributor &A) override {
5710 Value &V = getAssociatedValue();
5711 if (auto *C = dyn_cast<Constant>(&V)) {
5712 if (C->isThreadDependent())
5713 indicatePessimisticFixpoint();
5714 else
5715 indicateOptimisticFixpoint();
5716 return;
5717 }
5718 if (auto *CB = dyn_cast<CallBase>(&V))
5719 if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
5720 !CB->mayReadFromMemory()) {
5721 indicateOptimisticFixpoint();
5722 return;
5723 }
5724 if (auto *I = dyn_cast<Instruction>(&V)) {
5725 const auto *CI =
5726 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
5727 *I->getFunction());
5728 if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
5729 indicatePessimisticFixpoint();
5730 return;
5731 }
5732 }
5733 }
5734
5735 /// See AbstractAttribute::updateImpl(...).
5736 ChangeStatus updateImpl(Attributor &A) override {
5737 ChangeStatus Changed = ChangeStatus::UNCHANGED;
5738
5739 Value &V = getAssociatedValue();
5740 const Function *Scope = nullptr;
5741 if (auto *I = dyn_cast<Instruction>(&V))
5742 Scope = I->getFunction();
5743 if (auto *A = dyn_cast<Argument>(&V)) {
5744 Scope = A->getParent();
5745 if (!Scope->hasLocalLinkage())
5746 return Changed;
5747 }
5748 if (!Scope)
5749 return indicateOptimisticFixpoint();
5750
5751 bool IsKnownNoRecurse;
5753 A, this, IRPosition::function(*Scope), DepClassTy::OPTIONAL,
5754 IsKnownNoRecurse))
5755 return Changed;
5756
5757 auto UsePred = [&](const Use &U, bool &Follow) {
5758 const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
5759 if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
5760 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
5761 Follow = true;
5762 return true;
5763 }
5764 if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
5765 (isa<StoreInst>(UserI) &&
5766 cast<StoreInst>(UserI)->getValueOperand() != U.get()))
5767 return true;
5768 if (auto *CB = dyn_cast<CallBase>(UserI)) {
5769 // This check is not guaranteeing uniqueness but for now that we cannot
5770 // end up with two versions of \p U thinking it was one.
5772 if (!Callee || !Callee->hasLocalLinkage())
5773 return true;
5774 if (!CB->isArgOperand(&U))
5775 return false;
5776 const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
5778 DepClassTy::OPTIONAL);
5779 if (!ArgInstanceInfoAA ||
5780 !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
5781 return false;
5782 // If this call base might reach the scope again we might forward the
5783 // argument back here. This is very conservative.
5785 A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
5786 [Scope](const Function &Fn) { return &Fn != Scope; }))
5787 return false;
5788 return true;
5789 }
5790 return false;
5791 };
5792
5793 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
5794 if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
5795 auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
5796 if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
5797 AA::isDynamicallyUnique(A, *this, *Ptr))
5798 return true;
5799 }
5800 return false;
5801 };
5802
5803 if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
5804 DepClassTy::OPTIONAL,
5805 /* IgnoreDroppableUses */ true, EquivalentUseCB))
5806 return indicatePessimisticFixpoint();
5807
5808 return Changed;
5809 }
5810
5811 /// See AbstractState::getAsStr().
5812 const std::string getAsStr(Attributor *A) const override {
5813 return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
5814 }
5815
5816 /// See AbstractAttribute::trackStatistics()
5817 void trackStatistics() const override {}
5818};
5819
5820/// InstanceInfo attribute for floating values.
5821struct AAInstanceInfoFloating : AAInstanceInfoImpl {
5822 AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
5823 : AAInstanceInfoImpl(IRP, A) {}
5824};
5825
5826/// NoCapture attribute for function arguments.
5827struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
5828 AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
5829 : AAInstanceInfoFloating(IRP, A) {}
5830};
5831
5832/// InstanceInfo attribute for call site arguments.
5833struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
5834 AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
5835 : AAInstanceInfoImpl(IRP, A) {}
5836
5837 /// See AbstractAttribute::updateImpl(...).
5838 ChangeStatus updateImpl(Attributor &A) override {
5839 // TODO: Once we have call site specific value information we can provide
5840 // call site specific liveness information and then it makes
5841 // sense to specialize attributes for call sites arguments instead of
5842 // redirecting requests to the callee argument.
5843 Argument *Arg = getAssociatedArgument();
5844 if (!Arg)
5845 return indicatePessimisticFixpoint();
5846 const IRPosition &ArgPos = IRPosition::argument(*Arg);
5847 auto *ArgAA =
5848 A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
5849 if (!ArgAA)
5850 return indicatePessimisticFixpoint();
5851 return clampStateAndIndicateChange(getState(), ArgAA->getState());
5852 }
5853};
5854
5855/// InstanceInfo attribute for function return value.
5856struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
5857 AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
5858 : AAInstanceInfoImpl(IRP, A) {
5859 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5860 }
5861
5862 /// See AbstractAttribute::initialize(...).
5863 void initialize(Attributor &A) override {
5864 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5865 }
5866
5867 /// See AbstractAttribute::updateImpl(...).
5868 ChangeStatus updateImpl(Attributor &A) override {
5869 llvm_unreachable("InstanceInfo is not applicable to function returns!");
5870 }
5871};
5872
5873/// InstanceInfo attribute deduction for a call site return value.
5874struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
5875 AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
5876 : AAInstanceInfoFloating(IRP, A) {}
5877};
5878} // namespace
5879
5880/// ----------------------- Variable Capturing ---------------------------------
5882 Attribute::AttrKind ImpliedAttributeKind,
5883 bool IgnoreSubsumingPositions) {
5884 assert(ImpliedAttributeKind == Attribute::Captures &&
5885 "Unexpected attribute kind");
5886 Value &V = IRP.getAssociatedValue();
5887 if (!isa<Constant>(V) && !IRP.isArgumentPosition())
5888 return V.use_empty();
5889
5890 // You cannot "capture" null if it is not a valid pointer.
5891 if (isa<UndefValue>(V) ||
5895 return true;
5896 }
5897
5899 A.getAttrs(IRP, {Attribute::Captures}, Attrs,
5900 /* IgnoreSubsumingPositions */ true);
5901 for (const Attribute &Attr : Attrs)
5902 if (capturesNothing(Attr.getCaptureInfo()))
5903 return true;
5904
5906 if (Argument *Arg = IRP.getAssociatedArgument()) {
5908 A.getAttrs(IRPosition::argument(*Arg),
5909 {Attribute::Captures, Attribute::ByVal}, Attrs,
5910 /* IgnoreSubsumingPositions */ true);
5911 bool ArgNoCapture = any_of(Attrs, [](Attribute Attr) {
5912 return Attr.getKindAsEnum() == Attribute::ByVal ||
5914 });
5915 if (ArgNoCapture) {
5916 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(
5917 V.getContext(), CaptureInfo::none()));
5918 return true;
5919 }
5920 }
5921
5922 if (const Function *F = IRP.getAssociatedFunction()) {
5923 // Check what state the associated function can actually capture.
5926 if (State.isKnown(NO_CAPTURE)) {
5927 A.manifestAttrs(IRP, Attribute::getWithCaptureInfo(V.getContext(),
5929 return true;
5930 }
5931 }
5932
5933 return false;
5934}
5935
5936/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
5937/// depending on the ability of the function associated with \p IRP to capture
5938/// state in memory and through "returning/throwing", respectively.
5940 const Function &F,
5941 BitIntegerState &State) {
5942 // TODO: Once we have memory behavior attributes we should use them here.
5943
5944 // If we know we cannot communicate or write to memory, we do not care about
5945 // ptr2int anymore.
5946 bool ReadOnly = F.onlyReadsMemory();
5947 bool NoThrow = F.doesNotThrow();
5948 bool IsVoidReturn = F.getReturnType()->isVoidTy();
5949 if (ReadOnly && NoThrow && IsVoidReturn) {
5950 State.addKnownBits(NO_CAPTURE);
5951 return;
5952 }
5953
5954 // A function cannot capture state in memory if it only reads memory, it can
5955 // however return/throw state and the state might be influenced by the
5956 // pointer value, e.g., loading from a returned pointer might reveal a bit.
5957 if (ReadOnly)
5958 State.addKnownBits(NOT_CAPTURED_IN_MEM);
5959
5960 // A function cannot communicate state back if it does not through
5961 // exceptions and doesn not return values.
5962 if (NoThrow && IsVoidReturn)
5963 State.addKnownBits(NOT_CAPTURED_IN_RET);
5964
5965 // Check existing "returned" attributes.
5966 int ArgNo = IRP.getCalleeArgNo();
5967 if (!NoThrow || ArgNo < 0 ||
5968 !F.getAttributes().hasAttrSomewhere(Attribute::Returned))
5969 return;
5970
5971 for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
5972 if (F.hasParamAttribute(U, Attribute::Returned)) {
5973 if (U == unsigned(ArgNo))
5974 State.removeAssumedBits(NOT_CAPTURED_IN_RET);
5975 else if (ReadOnly)
5976 State.addKnownBits(NO_CAPTURE);
5977 else
5978 State.addKnownBits(NOT_CAPTURED_IN_RET);
5979 break;
5980 }
5981}
5982
5983namespace {
5984/// A class to hold the state of for no-capture attributes.
5985struct AANoCaptureImpl : public AANoCapture {
5986 AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}
5987
5988 /// See AbstractAttribute::initialize(...).
5989 void initialize(Attributor &A) override {
5990 bool IsKnown;
5992 A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
5993 (void)IsKnown;
5994 }
5995
5996 /// See AbstractAttribute::updateImpl(...).
5997 ChangeStatus updateImpl(Attributor &A) override;
5998
5999 /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
6000 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
6001 SmallVectorImpl<Attribute> &Attrs) const override {
6002 if (!isAssumedNoCaptureMaybeReturned())
6003 return;
6004
6005 if (isArgumentPosition()) {
6006 if (isAssumedNoCapture())
6007 Attrs.emplace_back(Attribute::get(Ctx, Attribute::Captures));
6008 else if (ManifestInternal)
6009 Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
6010 }
6011 }
6012
6013 /// See AbstractState::getAsStr().
6014 const std::string getAsStr(Attributor *A) const override {
6015 if (isKnownNoCapture())
6016 return "known not-captured";
6017 if (isAssumedNoCapture())
6018 return "assumed not-captured";
6019 if (isKnownNoCaptureMaybeReturned())
6020 return "known not-captured-maybe-returned";
6021 if (isAssumedNoCaptureMaybeReturned())
6022 return "assumed not-captured-maybe-returned";
6023 return "assumed-captured";
6024 }
6025
6026 /// Check the use \p U and update \p State accordingly. Return true if we
6027 /// should continue to update the state.
6028 bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
6029 bool &Follow) {
6030 Instruction *UInst = cast<Instruction>(U.getUser());
6031 LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
6032 << *UInst << "\n");
6033
6034 // Deal with ptr2int by following uses.
6035 if (isa<PtrToIntInst>(UInst)) {
6036 LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
6037 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6038 /* Return */ true);
6039 }
6040
6041 // For stores we already checked if we can follow them, if they make it
6042 // here we give up.
6043 if (isa<StoreInst>(UInst))
6044 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6045 /* Return */ true);
6046
6047 // Explicitly catch return instructions.
6048 if (isa<ReturnInst>(UInst)) {
6049 if (UInst->getFunction() == getAnchorScope())
6050 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
6051 /* Return */ true);
6052 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6053 /* Return */ true);
6054 }
6055
6056 // For now we only use special logic for call sites. However, the tracker
6057 // itself knows about a lot of other non-capturing cases already.
6058 auto *CB = dyn_cast<CallBase>(UInst);
6059 if (!CB || !CB->isArgOperand(&U))
6060 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6061 /* Return */ true);
6062
6063 unsigned ArgNo = CB->getArgOperandNo(&U);
6064 const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
6065 // If we have a abstract no-capture attribute for the argument we can use
6066 // it to justify a non-capture attribute here. This allows recursion!
6067 bool IsKnownNoCapture;
6068 const AANoCapture *ArgNoCaptureAA = nullptr;
6069 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
6070 A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6071 &ArgNoCaptureAA);
6072 if (IsAssumedNoCapture)
6073 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
6074 /* Return */ false);
6075 if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
6076 Follow = true;
6077 return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
6078 /* Return */ false);
6079 }
6080
6081 // Lastly, we could not find a reason no-capture can be assumed so we don't.
6082 return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
6083 /* Return */ true);
6084 }
6085
6086 /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
6087 /// \p CapturedInRet, then return true if we should continue updating the
6088 /// state.
6089 static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
6090 bool CapturedInInt, bool CapturedInRet) {
6091 LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
6092 << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
6093 if (CapturedInMem)
6094 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
6095 if (CapturedInInt)
6096 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
6097 if (CapturedInRet)
6098 State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
6099 return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
6100 }
6101};
6102
6103ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
6104 const IRPosition &IRP = getIRPosition();
6105 Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
6106 : &IRP.getAssociatedValue();
6107 if (!V)
6108 return indicatePessimisticFixpoint();
6109
6110 const Function *F =
6111 isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
6112
6113 // TODO: Is the checkForAllUses below useful for constants?
6114 if (!F)
6115 return indicatePessimisticFixpoint();
6116
6118 const IRPosition &FnPos = IRPosition::function(*F);
6119
6120 // Readonly means we cannot capture through memory.
6121 bool IsKnown;
6122 if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
6123 T.addKnownBits(NOT_CAPTURED_IN_MEM);
6124 if (IsKnown)
6125 addKnownBits(NOT_CAPTURED_IN_MEM);
6126 }
6127
6128 // Make sure all returned values are different than the underlying value.
6129 // TODO: we could do this in a more sophisticated way inside
6130 // AAReturnedValues, e.g., track all values that escape through returns
6131 // directly somehow.
6132 auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
6134 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,
6136 UsedAssumedInformation))
6137 return false;
6138 bool SeenConstant = false;
6139 for (const AA::ValueAndContext &VAC : Values) {
6140 if (isa<Constant>(VAC.getValue())) {
6141 if (SeenConstant)
6142 return false;
6143 SeenConstant = true;
6144 } else if (!isa<Argument>(VAC.getValue()) ||
6145 VAC.getValue() == getAssociatedArgument())
6146 return false;
6147 }
6148 return true;
6149 };
6150
6151 bool IsKnownNoUnwind;
6153 A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
6154 bool IsVoidTy = F->getReturnType()->isVoidTy();
6155 bool UsedAssumedInformation = false;
6156 if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
6157 T.addKnownBits(NOT_CAPTURED_IN_RET);
6158 if (T.isKnown(NOT_CAPTURED_IN_MEM))
6160 if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
6161 addKnownBits(NOT_CAPTURED_IN_RET);
6162 if (isKnown(NOT_CAPTURED_IN_MEM))
6163 return indicateOptimisticFixpoint();
6164 }
6165 }
6166 }
6167
6168 auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
6169 // TODO(captures): Make this more precise.
6170 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
6171 if (capturesNothing(CI))
6172 return true;
6173 if (CI.isPassthrough()) {
6174 Follow = true;
6175 return true;
6176 }
6177 return checkUse(A, T, U, Follow);
6178 };
6179
6180 if (!A.checkForAllUses(UseCheck, *this, *V))
6181 return indicatePessimisticFixpoint();
6182
6183 AANoCapture::StateType &S = getState();
6184 auto Assumed = S.getAssumed();
6185 S.intersectAssumedBits(T.getAssumed());
6186 if (!isAssumedNoCaptureMaybeReturned())
6187 return indicatePessimisticFixpoint();
6188 return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
6190}
6191
6192/// NoCapture attribute for function arguments.
6193struct AANoCaptureArgument final : AANoCaptureImpl {
6194 AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
6195 : AANoCaptureImpl(IRP, A) {}
6196
6197 /// See AbstractAttribute::trackStatistics()
6198 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
6199};
6200
6201/// NoCapture attribute for call site arguments.
6202struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
6203 AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
6204 : AANoCaptureImpl(IRP, A) {}
6205
6206 /// See AbstractAttribute::updateImpl(...).
6207 ChangeStatus updateImpl(Attributor &A) override {
6208 // TODO: Once we have call site specific value information we can provide
6209 // call site specific liveness information and then it makes
6210 // sense to specialize attributes for call sites arguments instead of
6211 // redirecting requests to the callee argument.
6212 Argument *Arg = getAssociatedArgument();
6213 if (!Arg)
6214 return indicatePessimisticFixpoint();
6215 const IRPosition &ArgPos = IRPosition::argument(*Arg);
6216 bool IsKnownNoCapture;
6217 const AANoCapture *ArgAA = nullptr;
6219 A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
6220 &ArgAA))
6221 return ChangeStatus::UNCHANGED;
6222 if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
6223 return indicatePessimisticFixpoint();
6224 return clampStateAndIndicateChange(getState(), ArgAA->getState());
6225 }
6226
6227 /// See AbstractAttribute::trackStatistics()
6228 void trackStatistics() const override {
6230 };
6231};
6232
6233/// NoCapture attribute for floating values.
6234struct AANoCaptureFloating final : AANoCaptureImpl {
6235 AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
6236 : AANoCaptureImpl(IRP, A) {}
6237
6238 /// See AbstractAttribute::trackStatistics()
6239 void trackStatistics() const override {
6241 }
6242};
6243
6244/// NoCapture attribute for function return value.
6245struct AANoCaptureReturned final : AANoCaptureImpl {
6246 AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
6247 : AANoCaptureImpl(IRP, A) {
6248 llvm_unreachable("NoCapture is not applicable to function returns!");
6249 }
6250
6251 /// See AbstractAttribute::initialize(...).
6252 void initialize(Attributor &A) override {
6253 llvm_unreachable("NoCapture is not applicable to function returns!");
6254 }
6255
6256 /// See AbstractAttribute::updateImpl(...).
6257 ChangeStatus updateImpl(Attributor &A) override {
6258 llvm_unreachable("NoCapture is not applicable to function returns!");
6259 }
6260
6261 /// See AbstractAttribute::trackStatistics()
6262 void trackStatistics() const override {}
6263};
6264
6265/// NoCapture attribute deduction for a call site return value.
6266struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
6267 AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
6268 : AANoCaptureImpl(IRP, A) {}
6269
6270 /// See AbstractAttribute::initialize(...).
6271 void initialize(Attributor &A) override {
6272 const Function *F = getAnchorScope();
6273 // Check what state the associated function can actually capture.
6274 determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
6275 }
6276
6277 /// See AbstractAttribute::trackStatistics()
6278 void trackStatistics() const override {
6280 }
6281};
6282} // namespace
6283
6284/// ------------------ Value Simplify Attribute ----------------------------
6285
6286bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
6287 // FIXME: Add a typecast support.
6290 if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
6291 return false;
6292
6293 LLVM_DEBUG({
6295 dbgs() << "[ValueSimplify] is assumed to be "
6296 << **SimplifiedAssociatedValue << "\n";
6297 else
6298 dbgs() << "[ValueSimplify] is assumed to be <none>\n";
6299 });
6300 return true;
6301}
6302
6303namespace {
6304struct AAValueSimplifyImpl : AAValueSimplify {
6305 AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
6306 : AAValueSimplify(IRP, A) {}
6307
6308 /// See AbstractAttribute::initialize(...).
6309 void initialize(Attributor &A) override {
6310 if (getAssociatedValue().getType()->isVoidTy())
6311 indicatePessimisticFixpoint();
6312 if (A.hasSimplificationCallback(getIRPosition()))
6313 indicatePessimisticFixpoint();
6314 }
6315
6316 /// See AbstractAttribute::getAsStr().
6317 const std::string getAsStr(Attributor *A) const override {
6318 LLVM_DEBUG({
6319 dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
6320 if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
6321 dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
6322 });
6323 return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
6324 : "not-simple";
6325 }
6326
6327 /// See AbstractAttribute::trackStatistics()
6328 void trackStatistics() const override {}
6329
6330 /// See AAValueSimplify::getAssumedSimplifiedValue()
6331 std::optional<Value *>
6332 getAssumedSimplifiedValue(Attributor &A) const override {
6333 return SimplifiedAssociatedValue;
6334 }
6335
6336 /// Ensure the return value is \p V with type \p Ty, if not possible return
6337 /// nullptr. If \p Check is true we will only verify such an operation would
6338 /// suceed and return a non-nullptr value if that is the case. No IR is
6339 /// generated or modified.
6340 static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
6341 bool Check) {
6342 if (auto *TypedV = AA::getWithType(V, Ty))
6343 return TypedV;
6344 if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
6345 return Check ? &V
6346 : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6347 &V, &Ty, "", CtxI->getIterator());
6348 return nullptr;
6349 }
6350
6351 /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
6352 /// If \p Check is true we will only verify such an operation would suceed and
6353 /// return a non-nullptr value if that is the case. No IR is generated or
6354 /// modified.
6355 static Value *reproduceInst(Attributor &A,
6356 const AbstractAttribute &QueryingAA,
6357 Instruction &I, Type &Ty, Instruction *CtxI,
6358 bool Check, ValueToValueMapTy &VMap) {
6359 assert(CtxI && "Cannot reproduce an instruction without context!");
6360 if (Check && (I.mayReadFromMemory() ||
6361 !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
6362 /* TLI */ nullptr)))
6363 return nullptr;
6364 for (Value *Op : I.operands()) {
6365 Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
6366 if (!NewOp) {
6367 assert(Check && "Manifest of new value unexpectedly failed!");
6368 return nullptr;
6369 }
6370 if (!Check)
6371 VMap[Op] = NewOp;
6372 }
6373 if (Check)
6374 return &I;
6375
6376 Instruction *CloneI = I.clone();
6377 // TODO: Try to salvage debug information here.
6378 CloneI->setDebugLoc(DebugLoc());
6379 VMap[&I] = CloneI;
6380 CloneI->insertBefore(CtxI->getIterator());
6381 RemapInstruction(CloneI, VMap);
6382 return CloneI;
6383 }
6384
6385 /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
6386 /// If \p Check is true we will only verify such an operation would suceed and
6387 /// return a non-nullptr value if that is the case. No IR is generated or
6388 /// modified.
6389 static Value *reproduceValue(Attributor &A,
6390 const AbstractAttribute &QueryingAA, Value &V,
6391 Type &Ty, Instruction *CtxI, bool Check,
6392 ValueToValueMapTy &VMap) {
6393 if (const auto &NewV = VMap.lookup(&V))
6394 return NewV;
6395 bool UsedAssumedInformation = false;
6396 std::optional<Value *> SimpleV = A.getAssumedSimplified(
6397 V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6398 if (!SimpleV.has_value())
6399 return PoisonValue::get(&Ty);
6400 Value *EffectiveV = &V;
6401 if (*SimpleV)
6402 EffectiveV = *SimpleV;
6403 if (auto *C = dyn_cast<Constant>(EffectiveV))
6404 return C;
6405 if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
6406 A.getInfoCache()))
6407 return ensureType(A, *EffectiveV, Ty, CtxI, Check);
6408 if (auto *I = dyn_cast<Instruction>(EffectiveV))
6409 if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
6410 return ensureType(A, *NewV, Ty, CtxI, Check);
6411 return nullptr;
6412 }
6413
6414 /// Return a value we can use as replacement for the associated one, or
6415 /// nullptr if we don't have one that makes sense.
6416 Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
6417 Value *NewV = SimplifiedAssociatedValue
6418 ? *SimplifiedAssociatedValue
6419 : UndefValue::get(getAssociatedType());
6420 if (NewV && NewV != &getAssociatedValue()) {
6421 ValueToValueMapTy VMap;
6422 // First verify we can reprduce the value with the required type at the
6423 // context location before we actually start modifying the IR.
6424 if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6425 /* CheckOnly */ true, VMap))
6426 return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
6427 /* CheckOnly */ false, VMap);
6428 }
6429 return nullptr;
6430 }
6431
6432 /// Helper function for querying AAValueSimplify and updating candidate.
6433 /// \param IRP The value position we are trying to unify with SimplifiedValue
6434 bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
6435 const IRPosition &IRP, bool Simplify = true) {
6436 bool UsedAssumedInformation = false;
6437 std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
6438 if (Simplify)
6439 QueryingValueSimplified = A.getAssumedSimplified(
6440 IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
6441 return unionAssumed(QueryingValueSimplified);
6442 }
6443
6444 /// Returns a candidate is found or not
6445 template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
6446 if (!getAssociatedValue().getType()->isIntegerTy())
6447 return false;
6448
6449 // This will also pass the call base context.
6450 const auto *AA =
6451 A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
6452 if (!AA)
6453 return false;
6454
6455 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
6456
6457 if (!COpt) {
6458 SimplifiedAssociatedValue = std::nullopt;
6459 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6460 return true;
6461 }
6462 if (auto *C = *COpt) {
6463 SimplifiedAssociatedValue = C;
6464 A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
6465 return true;
6466 }
6467 return false;
6468 }
6469
6470 bool askSimplifiedValueForOtherAAs(Attributor &A) {
6471 if (askSimplifiedValueFor<AAValueConstantRange>(A))
6472 return true;
6473 if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
6474 return true;
6475 return false;
6476 }
6477
6478 /// See AbstractAttribute::manifest(...).
6479 ChangeStatus manifest(Attributor &A) override {
6480 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6481 for (auto &U : getAssociatedValue().uses()) {
6482 // Check if we need to adjust the insertion point to make sure the IR is
6483 // valid.
6484 Instruction *IP = dyn_cast<Instruction>(U.getUser());
6485 if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
6486 IP = PHI->getIncomingBlock(U)->getTerminator();
6487 if (auto *NewV = manifestReplacementValue(A, IP)) {
6488 LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
6489 << " -> " << *NewV << " :: " << *this << "\n");
6490 if (A.changeUseAfterManifest(U, *NewV))
6491 Changed = ChangeStatus::CHANGED;
6492 }
6493 }
6494
6495 return Changed | AAValueSimplify::manifest(A);
6496 }
6497
6498 /// See AbstractState::indicatePessimisticFixpoint(...).
6499 ChangeStatus indicatePessimisticFixpoint() override {
6500 SimplifiedAssociatedValue = &getAssociatedValue();
6501 return AAValueSimplify::indicatePessimisticFixpoint();
6502 }
6503};
6504
6505struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
6506 AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
6507 : AAValueSimplifyImpl(IRP, A) {}
6508
6509 void initialize(Attributor &A) override {
6510 AAValueSimplifyImpl::initialize(A);
6511 if (A.hasAttr(getIRPosition(),
6512 {Attribute::InAlloca, Attribute::Preallocated,
6513 Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
6514 /* IgnoreSubsumingPositions */ true))
6515 indicatePessimisticFixpoint();
6516 }
6517
6518 /// See AbstractAttribute::updateImpl(...).
6519 ChangeStatus updateImpl(Attributor &A) override {
6520 // Byval is only replacable if it is readonly otherwise we would write into
6521 // the replaced value and not the copy that byval creates implicitly.
6522 Argument *Arg = getAssociatedArgument();
6523 if (Arg->hasByValAttr()) {
6524 // TODO: We probably need to verify synchronization is not an issue, e.g.,
6525 // there is no race by not copying a constant byval.
6526 bool IsKnown;
6527 if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
6528 return indicatePessimisticFixpoint();
6529 }
6530
6531 auto Before = SimplifiedAssociatedValue;
6532
6533 auto PredForCallSite = [&](AbstractCallSite ACS) {
6534 const IRPosition &ACSArgPos =
6535 IRPosition::callsite_argument(ACS, getCallSiteArgNo());
6536 // Check if a coresponding argument was found or if it is on not
6537 // associated (which can happen for callback calls).
6538 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
6539 return false;
6540
6541 // Simplify the argument operand explicitly and check if the result is
6542 // valid in the current scope. This avoids refering to simplified values
6543 // in other functions, e.g., we don't want to say a an argument in a
6544 // static function is actually an argument in a different function.
6545 bool UsedAssumedInformation = false;
6546 std::optional<Constant *> SimpleArgOp =
6547 A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
6548 if (!SimpleArgOp)
6549 return true;
6550 if (!*SimpleArgOp)
6551 return false;
6552 if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
6553 return false;
6554 return unionAssumed(*SimpleArgOp);
6555 };
6556
6557 // Generate a answer specific to a call site context.
6558 bool Success;
6559 bool UsedAssumedInformation = false;
6560 if (hasCallBaseContext() &&
6561 getCallBaseContext()->getCalledOperand() == Arg->getParent())
6562 Success = PredForCallSite(
6563 AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
6564 else
6565 Success = A.checkForAllCallSites(PredForCallSite, *this, true,
6566 UsedAssumedInformation);
6567
6568 if (!Success)
6569 if (!askSimplifiedValueForOtherAAs(A))
6570 return indicatePessimisticFixpoint();
6571
6572 // If a candidate was found in this update, return CHANGED.
6573 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6574 : ChangeStatus ::CHANGED;
6575 }
6576
6577 /// See AbstractAttribute::trackStatistics()
6578 void trackStatistics() const override {
6579 STATS_DECLTRACK_ARG_ATTR(value_simplify)
6580 }
6581};
6582
6583struct AAValueSimplifyReturned : AAValueSimplifyImpl {
6584 AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
6585 : AAValueSimplifyImpl(IRP, A) {}
6586
6587 /// See AAValueSimplify::getAssumedSimplifiedValue()
6588 std::optional<Value *>
6589 getAssumedSimplifiedValue(Attributor &A) const override {
6590 if (!isValidState())
6591 return nullptr;
6592 return SimplifiedAssociatedValue;
6593 }
6594
6595 /// See AbstractAttribute::updateImpl(...).
6596 ChangeStatus updateImpl(Attributor &A) override {
6597 auto Before = SimplifiedAssociatedValue;
6598
6599 auto ReturnInstCB = [&](Instruction &I) {
6600 auto &RI = cast<ReturnInst>(I);
6601 return checkAndUpdate(
6602 A, *this,
6603 IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
6604 };
6605
6606 bool UsedAssumedInformation = false;
6607 if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
6608 UsedAssumedInformation))
6609 if (!askSimplifiedValueForOtherAAs(A))
6610 return indicatePessimisticFixpoint();
6611
6612 // If a candidate was found in this update, return CHANGED.
6613 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6614 : ChangeStatus ::CHANGED;
6615 }
6616
6617 ChangeStatus manifest(Attributor &A) override {
6618 // We queried AAValueSimplify for the returned values so they will be
6619 // replaced if a simplified form was found. Nothing to do here.
6620 return ChangeStatus::UNCHANGED;
6621 }
6622
6623 /// See AbstractAttribute::trackStatistics()
6624 void trackStatistics() const override {
6625 STATS_DECLTRACK_FNRET_ATTR(value_simplify)
6626 }
6627};
6628
6629struct AAValueSimplifyFloating : AAValueSimplifyImpl {
6630 AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
6631 : AAValueSimplifyImpl(IRP, A) {}
6632
6633 /// See AbstractAttribute::initialize(...).
6634 void initialize(Attributor &A) override {
6635 AAValueSimplifyImpl::initialize(A);
6636 Value &V = getAnchorValue();
6637
6638 // TODO: add other stuffs
6639 if (isa<Constant>(V))
6640 indicatePessimisticFixpoint();
6641 }
6642
6643 /// See AbstractAttribute::updateImpl(...).
6644 ChangeStatus updateImpl(Attributor &A) override {
6645 auto Before = SimplifiedAssociatedValue;
6646 if (!askSimplifiedValueForOtherAAs(A))
6647 return indicatePessimisticFixpoint();
6648
6649 // If a candidate was found in this update, return CHANGED.
6650 return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
6651 : ChangeStatus ::CHANGED;
6652 }
6653
6654 /// See AbstractAttribute::trackStatistics()
6655 void trackStatistics() const override {
6656 STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
6657 }
6658};
6659
6660struct AAValueSimplifyFunction : AAValueSimplifyImpl {
6661 AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
6662 : AAValueSimplifyImpl(IRP, A) {}
6663
6664 /// See AbstractAttribute::initialize(...).
6665 void initialize(Attributor &A) override {
6666 SimplifiedAssociatedValue = nullptr;
6667 indicateOptimisticFixpoint();
6668 }
6669 /// See AbstractAttribute::initialize(...).
6670 ChangeStatus updateImpl(Attributor &A) override {
6672 "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
6673 }
6674 /// See AbstractAttribute::trackStatistics()
6675 void trackStatistics() const override {
6676 STATS_DECLTRACK_FN_ATTR(value_simplify)
6677 }
6678};
6679
6680struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
6681 AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
6682 : AAValueSimplifyFunction(IRP, A) {}
6683 /// See AbstractAttribute::trackStatistics()
6684 void trackStatistics() const override {
6685 STATS_DECLTRACK_CS_ATTR(value_simplify)
6686 }
6687};
6688
6689struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
6690 AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
6691 : AAValueSimplifyImpl(IRP, A) {}
6692
6693 void initialize(Attributor &A) override {
6694 AAValueSimplifyImpl::initialize(A);
6695 Function *Fn = getAssociatedFunction();
6696 assert(Fn && "Did expect an associted function");
6697 for (Argument &Arg : Fn->args()) {
6698 if (Arg.hasReturnedAttr()) {
6699 auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
6700 Arg.getArgNo());
6702 checkAndUpdate(A, *this, IRP))
6703 indicateOptimisticFixpoint();
6704 else
6705 indicatePessimisticFixpoint();
6706 return;
6707 }
6708 }
6709 }
6710
6711 /// See AbstractAttribute::updateImpl(...).
6712 ChangeStatus updateImpl(Attributor &A) override {
6713 return indicatePessimisticFixpoint();
6714 }
6715
6716 void trackStatistics() const override {
6717 STATS_DECLTRACK_CSRET_ATTR(value_simplify)
6718 }
6719};
6720
6721struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
6722 AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
6723 : AAValueSimplifyFloating(IRP, A) {}
6724
6725 /// See AbstractAttribute::manifest(...).
6726 ChangeStatus manifest(Attributor &A) override {
6727 ChangeStatus Changed = ChangeStatus::UNCHANGED;
6728 // TODO: We should avoid simplification duplication to begin with.
6729 auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
6730 IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
6731 if (FloatAA && FloatAA->getState().isValidState())
6732 return Changed;
6733
6734 if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
6735 Use &U = cast<CallBase>(&getAnchorValue())
6736 ->getArgOperandUse(getCallSiteArgNo());
6737 if (A.changeUseAfterManifest(U, *NewV))
6738 Changed = ChangeStatus::CHANGED;
6739 }
6740
6741 return Changed | AAValueSimplify::manifest(A);
6742 }
6743
6744 void trackStatistics() const override {
6745 STATS_DECLTRACK_CSARG_ATTR(value_simplify)
6746 }
6747};
6748} // namespace
6749
6750/// ----------------------- Heap-To-Stack Conversion ---------------------------
6751namespace {
6752struct AAHeapToStackFunction final : public AAHeapToStack {
6753
6754 static bool isGlobalizedLocal(const CallBase &CB) {
6755 Attribute A = CB.getFnAttr("alloc-family");
6756 return A.isValid() && A.getValueAsString() == "__kmpc_alloc_shared";
6757 }
6758
6759 struct AllocationInfo {
6760 /// The call that allocates the memory.
6761 CallBase *const CB;
6762
6763 /// Whether this allocation is an OpenMP globalized local variable.
6764 bool IsGlobalizedLocal = false;
6765
6766 /// The status wrt. a rewrite.
6767 enum {
6768 STACK_DUE_TO_USE,
6769 STACK_DUE_TO_FREE,
6770 INVALID,
6771 } Status = STACK_DUE_TO_USE;
6772
6773 /// Flag to indicate if we encountered a use that might free this allocation
6774 /// but which is not in the deallocation infos.
6775 bool HasPotentiallyFreeingUnknownUses = false;
6776
6777 /// Flag to indicate that we should place the new alloca in the function
6778 /// entry block rather than where the call site (CB) is.
6779 bool MoveAllocaIntoEntry = true;
6780
6781 /// The set of free calls that use this allocation.
6782 SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
6783 };
6784
6785 struct DeallocationInfo {
6786 /// The call that deallocates the memory.
6787 CallBase *const CB;
6788 /// The value freed by the call.
6789 Value *FreedOp;
6790
6791 /// Flag to indicate if we don't know all objects this deallocation might
6792 /// free.
6793 bool MightFreeUnknownObjects = false;
6794
6795 /// The set of allocation calls that are potentially freed.
6796 SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
6797 };
6798
6799 AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
6800 : AAHeapToStack(IRP, A) {}
6801
6802 ~AAHeapToStackFunction() override {
6803 // Ensure we call the destructor so we release any memory allocated in the
6804 // sets.
6805 for (auto &It : AllocationInfos)
6806 It.second->~AllocationInfo();
6807 for (auto &It : DeallocationInfos)
6808 It.second->~DeallocationInfo();
6809 }
6810
6811 void initialize(Attributor &A) override {
6812 AAHeapToStack::initialize(A);
6813
6814 const Function *F = getAnchorScope();
6815 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6816
6817 auto AllocationIdentifierCB = [&](Instruction &I) {
6818 CallBase *CB = dyn_cast<CallBase>(&I);
6819 if (!CB)
6820 return true;
6821 if (Value *FreedOp = getFreedOperand(CB, TLI)) {
6822 DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
6823 return true;
6824 }
6825 // To do heap to stack, we need to know that the allocation itself is
6826 // removable once uses are rewritten, and that we can initialize the
6827 // alloca to the same pattern as the original allocation result.
6828 if (isRemovableAlloc(CB, TLI)) {
6829 auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
6830 if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
6831 AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
6832 AllocationInfos[CB] = AI;
6833 AI->IsGlobalizedLocal = isGlobalizedLocal(*CB);
6834 }
6835 }
6836 return true;
6837 };
6838
6839 bool UsedAssumedInformation = false;
6840 bool Success = A.checkForAllCallLikeInstructions(
6841 AllocationIdentifierCB, *this, UsedAssumedInformation,
6842 /* CheckBBLivenessOnly */ false,
6843 /* CheckPotentiallyDead */ true);
6844 (void)Success;
6845 assert(Success && "Did not expect the call base visit callback to fail!");
6846
6848 [](const IRPosition &, const AbstractAttribute *,
6849 bool &) -> std::optional<Value *> { return nullptr; };
6850 for (const auto &It : AllocationInfos)
6851 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6852 SCB);
6853 for (const auto &It : DeallocationInfos)
6854 A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
6855 SCB);
6856 }
6857
6858 const std::string getAsStr(Attributor *A) const override {
6859 unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
6860 for (const auto &It : AllocationInfos) {
6861 if (It.second->Status == AllocationInfo::INVALID)
6862 ++NumInvalidMallocs;
6863 else
6864 ++NumH2SMallocs;
6865 }
6866 return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
6867 std::to_string(NumInvalidMallocs);
6868 }
6869
6870 /// See AbstractAttribute::trackStatistics().
6871 void trackStatistics() const override {
6872 STATS_DECL(
6873 MallocCalls, Function,
6874 "Number of malloc/calloc/aligned_alloc calls converted to allocas");
6875 for (const auto &It : AllocationInfos)
6876 if (It.second->Status != AllocationInfo::INVALID)
6877 ++BUILD_STAT_NAME(MallocCalls, Function);
6878 }
6879
6880 bool isAssumedHeapToStack(const CallBase &CB) const override {
6881 if (isValidState())
6882 if (AllocationInfo *AI =
6883 AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
6884 return AI->Status != AllocationInfo::INVALID;
6885 return false;
6886 }
6887
6888 bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
6889 if (!isValidState())
6890 return false;
6891
6892 for (const auto &It : AllocationInfos) {
6893 AllocationInfo &AI = *It.second;
6894 if (AI.Status == AllocationInfo::INVALID)
6895 continue;
6896
6897 if (AI.PotentialFreeCalls.count(&CB))
6898 return true;
6899 }
6900
6901 return false;
6902 }
6903
6904 ChangeStatus manifest(Attributor &A) override {
6905 assert(getState().isValidState() &&
6906 "Attempted to manifest an invalid state!");
6907
6908 ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
6909 Function *F = getAnchorScope();
6910 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
6911
6912 for (auto &It : AllocationInfos) {
6913 AllocationInfo &AI = *It.second;
6914 if (AI.Status == AllocationInfo::INVALID)
6915 continue;
6916
6917 for (CallBase *FreeCall : AI.PotentialFreeCalls) {
6918 LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
6919 A.deleteAfterManifest(*FreeCall);
6920 HasChanged = ChangeStatus::CHANGED;
6921 }
6922
6923 LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
6924 << "\n");
6925
6926 auto Remark = [&](OptimizationRemark OR) {
6927 if (AI.IsGlobalizedLocal)
6928 return OR << "Moving globalized variable to the stack.";
6929 return OR << "Moving memory allocation from the heap to the stack.";
6930 };
6931 if (AI.IsGlobalizedLocal)
6932 A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
6933 else
6934 A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);
6935
6936 const DataLayout &DL = A.getInfoCache().getDL();
6937 Value *Size;
6938 std::optional<APInt> SizeAPI = getSize(A, *this, AI);
6939 if (SizeAPI) {
6940 Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
6941 } else {
6942 ObjectSizeOpts Opts;
6943 ObjectSizeOffsetEvaluator Eval(*AI.CB->getModule(), TLI, Opts);
6944 SizeOffsetValue SizeOffsetPair = Eval.compute(AI.CB);
6945 assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
6946 cast<ConstantInt>(SizeOffsetPair.Offset)->isZero());
6947 Size = SizeOffsetPair.Size;
6948 }
6949
6950 BasicBlock::iterator IP = AI.MoveAllocaIntoEntry
6951 ? F->getEntryBlock().begin()
6952 : AI.CB->getIterator();
6953
6954 Align Alignment(1);
6955 if (MaybeAlign RetAlign = AI.CB->getRetAlign())
6956 Alignment = std::max(Alignment, *RetAlign);
6957 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
6958 std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
6959 assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
6960 "Expected an alignment during manifest!");
6961 Alignment =
6962 std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
6963 }
6964
6965 // TODO: Hoist the alloca towards the function entry.
6966 unsigned AS = DL.getAllocaAddrSpace();
6967 Instruction *Alloca =
6968 new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
6969 AI.CB->getName() + ".h2s", IP);
6970
6971 if (Alloca->getType() != AI.CB->getType())
6972 Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
6973 Alloca, AI.CB->getType(), "malloc_cast", AI.CB->getIterator());
6974
6975 auto *I8Ty = Type::getInt8Ty(F->getContext());
6976 auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
6977 assert(InitVal &&
6978 "Must be able to materialize initial memory state of allocation");
6979
6980 A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);
6981
6982 if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
6983 auto *NBB = II->getNormalDest();
6984 UncondBrInst::Create(NBB, AI.CB->getParent());
6985 A.deleteAfterManifest(*AI.CB);
6986 } else {
6987 A.deleteAfterManifest(*AI.CB);
6988 }
6989
6990 // Initialize the alloca with the same value as used by the allocation
6991 // function. We can skip undef as the initial value of an alloc is
6992 // undef, and the memset would simply end up being DSEd.
6993 if (!isa<UndefValue>(InitVal)) {
6994 IRBuilder<> Builder(Alloca->getNextNode());
6995 // TODO: Use alignment above if align!=1
6996 Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
6997 }
6998 HasChanged = ChangeStatus::CHANGED;
6999 }
7000
7001 return HasChanged;
7002 }
7003
7004 std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
7005 Value &V) {
7006 bool UsedAssumedInformation = false;
7007 std::optional<Constant *> SimpleV =
7008 A.getAssumedConstant(V, AA, UsedAssumedInformation);
7009 if (!SimpleV)
7010 return APInt(64, 0);
7011 if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
7012 return CI->getValue();
7013 return std::nullopt;
7014 }
7015
7016 std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
7017 AllocationInfo &AI) {
7018 auto Mapper = [&](const Value *V) -> const Value * {
7019 bool UsedAssumedInformation = false;
7020 if (std::optional<Constant *> SimpleV =
7021 A.getAssumedConstant(*V, AA, UsedAssumedInformation))
7022 if (*SimpleV)
7023 return *SimpleV;
7024 return V;
7025 };
7026
7027 const Function *F = getAnchorScope();
7028 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
7029 return getAllocSize(AI.CB, TLI, Mapper);
7030 }
7031
7032 /// Collection of all malloc-like calls in a function with associated
7033 /// information.
7034 MapVector<CallBase *, AllocationInfo *> AllocationInfos;
7035
7036 /// Collection of all free-like calls in a function with associated
7037 /// information.
7038 MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;
7039
7040 ChangeStatus updateImpl(Attributor &A) override;
7041};
7042
7043ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
7045 const Function *F = getAnchorScope();
7046 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
7047
7048 const auto *LivenessAA =
7049 A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);
7050
7051 MustBeExecutedContextExplorer *Explorer =
7052 A.getInfoCache().getMustBeExecutedContextExplorer();
7053
7054 bool StackIsAccessibleByOtherThreads =
7055 A.getInfoCache().stackIsAccessibleByOtherThreads();
7056
7057 LoopInfo *LI =
7058 A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
7059 std::optional<bool> MayContainIrreducibleControl;
7060 auto IsInLoop = [&](BasicBlock &BB) {
7061 if (&F->getEntryBlock() == &BB)
7062 return false;
7063 if (!MayContainIrreducibleControl.has_value())
7064 MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
7065 if (*MayContainIrreducibleControl)
7066 return true;
7067 if (!LI)
7068 return true;
7069 return LI->getLoopFor(&BB) != nullptr;
7070 };
7071
7072 // Flag to ensure we update our deallocation information at most once per
7073 // updateImpl call and only if we use the free check reasoning.
7074 bool HasUpdatedFrees = false;
7075
7076 auto UpdateFrees = [&]() {
7077 HasUpdatedFrees = true;
7078
7079 for (auto &It : DeallocationInfos) {
7080 DeallocationInfo &DI = *It.second;
7081 // For now we cannot use deallocations that have unknown inputs, skip
7082 // them.
7083 if (DI.MightFreeUnknownObjects)
7084 continue;
7085
7086 // No need to analyze dead calls, ignore them instead.
7087 bool UsedAssumedInformation = false;
7088 if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,
7089 /* CheckBBLivenessOnly */ true))
7090 continue;
7091
7092 // Use the non-optimistic version to get the freed object.
7093 Value *Obj = getUnderlyingObject(DI.FreedOp);
7094 if (!Obj) {
7095 LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
7096 DI.MightFreeUnknownObjects = true;
7097 continue;
7098 }
7099
7100 // Free of null and undef can be ignored as no-ops (or UB in the latter
7101 // case).
7103 continue;
7104
7105 CallBase *ObjCB = dyn_cast<CallBase>(Obj);
7106 if (!ObjCB) {
7107 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
7108 << "\n");
7109 DI.MightFreeUnknownObjects = true;
7110 continue;
7111 }
7112
7113 AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
7114 if (!AI) {
7115 LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
7116 << "\n");
7117 DI.MightFreeUnknownObjects = true;
7118 continue;
7119 }
7120
7121 DI.PotentialAllocationCalls.insert(ObjCB);
7122 }
7123 };
7124
7125 auto FreeCheck = [&](AllocationInfo &AI) {
7126 // If the stack is not accessible by other threads, the "must-free" logic
7127 // doesn't apply as the pointer could be shared and needs to be places in
7128 // "shareable" memory.
7129 if (!StackIsAccessibleByOtherThreads) {
7130 bool IsKnownNoSycn;
7132 A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {
7133 LLVM_DEBUG(
7134 dbgs() << "[H2S] found an escaping use, stack is not accessible by "
7135 "other threads and function is not nosync:\n");
7136 return false;
7137 }
7138 }
7139 if (!HasUpdatedFrees)
7140 UpdateFrees();
7141
7142 // TODO: Allow multi exit functions that have different free calls.
7143 if (AI.PotentialFreeCalls.size() != 1) {
7144 LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
7145 << AI.PotentialFreeCalls.size() << "\n");
7146 return false;
7147 }
7148 CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
7149 DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
7150 if (!DI) {
7151 LLVM_DEBUG(
7152 dbgs() << "[H2S] unique free call was not known as deallocation call "
7153 << *UniqueFree << "\n");
7154 return false;
7155 }
7156 if (DI->MightFreeUnknownObjects) {
7157 LLVM_DEBUG(
7158 dbgs() << "[H2S] unique free call might free unknown allocations\n");
7159 return false;
7160 }
7161 if (DI->PotentialAllocationCalls.empty())
7162 return true;
7163 if (DI->PotentialAllocationCalls.size() > 1) {
7164 LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
7165 << DI->PotentialAllocationCalls.size()
7166 << " different allocations\n");
7167 return false;
7168 }
7169 if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
7170 LLVM_DEBUG(
7171 dbgs()
7172 << "[H2S] unique free call not known to free this allocation but "
7173 << **DI->PotentialAllocationCalls.begin() << "\n");
7174 return false;
7175 }
7176
7177 // __kmpc_alloc_shared and __kmpc_free_shared are by construction matched.
7178 if (!AI.IsGlobalizedLocal) {
7179 Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
7180 if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
7181 LLVM_DEBUG(dbgs() << "[H2S] unique free call might not be executed "
7182 "with the allocation "
7183 << *UniqueFree << "\n");
7184 return false;
7185 }
7186 }
7187 return true;
7188 };
7189
7190 auto UsesCheck = [&](AllocationInfo &AI) {
7191 bool ValidUsesOnly = true;
7192
7193 auto Pred = [&](const Use &U, bool &Follow) -> bool {
7194 Instruction *UserI = cast<Instruction>(U.getUser());
7195 if (isa<LoadInst>(UserI))
7196 return true;
7197 if (auto *SI = dyn_cast<StoreInst>(UserI)) {
7198 if (SI->getValueOperand() == U.get()) {
7200 << "[H2S] escaping store to memory: " << *UserI << "\n");
7201 ValidUsesOnly = false;
7202 } else {
7203 // A store into the malloc'ed memory is fine.
7204 }
7205 return true;
7206 }
7207 if (auto *CB = dyn_cast<CallBase>(UserI)) {
7208 if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
7209 return true;
7210 if (DeallocationInfos.count(CB)) {
7211 AI.PotentialFreeCalls.insert(CB);
7212 return true;
7213 }
7214
7215 unsigned ArgNo = CB->getArgOperandNo(&U);
7216 auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);
7217
7218 bool IsKnownNoCapture;
7219 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7220 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);
7221
7222 // If a call site argument use is nofree, we are fine.
7223 bool IsKnownNoFree;
7224 bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
7225 A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);
7226
7227 if (!IsAssumedNoCapture ||
7228 (!AI.IsGlobalizedLocal && !IsAssumedNoFree)) {
7229 AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;
7230
7231 // Emit a missed remark if this is missed OpenMP globalization.
7232 auto Remark = [&](OptimizationRemarkMissed ORM) {
7233 return ORM
7234 << "Could not move globalized variable to the stack. "
7235 "Variable is potentially captured in call. Mark "
7236 "parameter as `__attribute__((noescape))` to override.";
7237 };
7238
7239 if (ValidUsesOnly && AI.IsGlobalizedLocal)
7240 A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);
7241
7242 LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
7243 ValidUsesOnly = false;
7244 }
7245 return true;
7246 }
7247
7248 if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
7249 isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
7250 Follow = true;
7251 return true;
7252 }
7253 // Unknown user for which we can not track uses further (in a way that
7254 // makes sense).
7255 LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
7256 ValidUsesOnly = false;
7257 return true;
7258 };
7259 if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
7260 DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
7261 [&](const Use &OldU, const Use &NewU) {
7262 auto *SI = dyn_cast<StoreInst>(OldU.getUser());
7263 return !SI || StackIsAccessibleByOtherThreads ||
7264 AA::isAssumedThreadLocalObject(
7265 A, *SI->getPointerOperand(), *this);
7266 }))
7267 return false;
7268 return ValidUsesOnly;
7269 };
7270
7271 // The actual update starts here. We look at all allocations and depending on
7272 // their status perform the appropriate check(s).
7273 for (auto &It : AllocationInfos) {
7274 AllocationInfo &AI = *It.second;
7275 if (AI.Status == AllocationInfo::INVALID)
7276 continue;
7277
7278 if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
7279 std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
7280 if (!APAlign) {
7281 // Can't generate an alloca which respects the required alignment
7282 // on the allocation.
7283 LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
7284 << "\n");
7285 AI.Status = AllocationInfo::INVALID;
7287 continue;
7288 }
7289 if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
7290 !APAlign->isPowerOf2()) {
7291 LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
7292 << "\n");
7293 AI.Status = AllocationInfo::INVALID;
7295 continue;
7296 }
7297 }
7298
7299 std::optional<APInt> Size = getSize(A, *this, AI);
7300 if (!AI.IsGlobalizedLocal && MaxHeapToStackSize != -1) {
7301 if (!Size || Size->ugt(MaxHeapToStackSize)) {
7302 LLVM_DEBUG({
7303 if (!Size)
7304 dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
7305 else
7306 dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
7307 << MaxHeapToStackSize << "\n";
7308 });
7309
7310 AI.Status = AllocationInfo::INVALID;
7312 continue;
7313 }
7314 }
7315
7316 switch (AI.Status) {
7317 case AllocationInfo::STACK_DUE_TO_USE:
7318 if (UsesCheck(AI))
7319 break;
7320 AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
7321 [[fallthrough]];
7322 case AllocationInfo::STACK_DUE_TO_FREE:
7323 if (FreeCheck(AI))
7324 break;
7325 AI.Status = AllocationInfo::INVALID;
7327 break;
7328 case AllocationInfo::INVALID:
7329 llvm_unreachable("Invalid allocations should never reach this point!");
7330 };
7331
7332 // Check if we still think we can move it into the entry block. If the
7333 // alloca comes from a converted __kmpc_alloc_shared then we can usually
7334 // ignore the potential complications associated with loops.
7335 bool IsGlobalizedLocal = AI.IsGlobalizedLocal;
7336 if (AI.MoveAllocaIntoEntry &&
7337 (!Size.has_value() ||
7338 (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
7339 AI.MoveAllocaIntoEntry = false;
7340 }
7341
7342 return Changed;
7343}
7344} // namespace
7345
7346/// ----------------------- Privatizable Pointers ------------------------------
7347namespace {
7348struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
7349 AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
7350 : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}
7351
7352 ChangeStatus indicatePessimisticFixpoint() override {
7353 AAPrivatizablePtr::indicatePessimisticFixpoint();
7354 PrivatizableType = nullptr;
7355 return ChangeStatus::CHANGED;
7356 }
7357
7358 /// Identify the type we can chose for a private copy of the underlying
7359 /// argument. std::nullopt means it is not clear yet, nullptr means there is
7360 /// none.
7361 virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;
7362
7363 /// Return a privatizable type that encloses both T0 and T1.
7364 /// TODO: This is merely a stub for now as we should manage a mapping as well.
7365 std::optional<Type *> combineTypes(std::optional<Type *> T0,
7366 std::optional<Type *> T1) {
7367 if (!T0)
7368 return T1;
7369 if (!T1)
7370 return T0;
7371 if (T0 == T1)
7372 return T0;
7373 return nullptr;
7374 }
7375
7376 std::optional<Type *> getPrivatizableType() const override {
7377 return PrivatizableType;
7378 }
7379
7380 const std::string getAsStr(Attributor *A) const override {
7381 return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
7382 }
7383
7384protected:
7385 std::optional<Type *> PrivatizableType;
7386};
7387
7388// TODO: Do this for call site arguments (probably also other values) as well.
7389
7390struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
7391 AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
7392 : AAPrivatizablePtrImpl(IRP, A) {}
7393
7394 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7395 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7396 // If this is a byval argument and we know all the call sites (so we can
7397 // rewrite them), there is no need to check them explicitly.
7398 bool UsedAssumedInformation = false;
7400 A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,
7401 /* IgnoreSubsumingPositions */ true);
7402 if (!Attrs.empty() &&
7403 A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
7404 true, UsedAssumedInformation))
7405 return Attrs[0].getValueAsType();
7406
7407 std::optional<Type *> Ty;
7408 unsigned ArgNo = getIRPosition().getCallSiteArgNo();
7409
7410 // Make sure the associated call site argument has the same type at all call
7411 // sites and it is an allocation we know is safe to privatize, for now that
7412 // means we only allow alloca instructions.
7413 // TODO: We can additionally analyze the accesses in the callee to create
7414 // the type from that information instead. That is a little more
7415 // involved and will be done in a follow up patch.
7416 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7417 IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
7418 // Check if a coresponding argument was found or if it is one not
7419 // associated (which can happen for callback calls).
7420 if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
7421 return false;
7422
7423 // Check that all call sites agree on a type.
7424 auto *PrivCSArgAA =
7425 A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
7426 if (!PrivCSArgAA)
7427 return false;
7428 std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();
7429
7430 LLVM_DEBUG({
7431 dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
7432 if (CSTy && *CSTy)
7433 (*CSTy)->print(dbgs());
7434 else if (CSTy)
7435 dbgs() << "<nullptr>";
7436 else
7437 dbgs() << "<none>";
7438 });
7439
7440 Ty = combineTypes(Ty, CSTy);
7441
7442 LLVM_DEBUG({
7443 dbgs() << " : New Type: ";
7444 if (Ty && *Ty)
7445 (*Ty)->print(dbgs());
7446 else if (Ty)
7447 dbgs() << "<nullptr>";
7448 else
7449 dbgs() << "<none>";
7450 dbgs() << "\n";
7451 });
7452
7453 return !Ty || *Ty;
7454 };
7455
7456 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7457 UsedAssumedInformation))
7458 return nullptr;
7459 return Ty;
7460 }
7461
7462 /// See AbstractAttribute::updateImpl(...).
7463 ChangeStatus updateImpl(Attributor &A) override {
7464 PrivatizableType = identifyPrivatizableType(A);
7465 if (!PrivatizableType)
7466 return ChangeStatus::UNCHANGED;
7467 if (!*PrivatizableType)
7468 return indicatePessimisticFixpoint();
7469
7470 // The dependence is optional so we don't give up once we give up on the
7471 // alignment.
7472 A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
7473 DepClassTy::OPTIONAL);
7474
7475 // Avoid arguments with padding for now.
7476 if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
7477 !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
7478 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
7479 return indicatePessimisticFixpoint();
7480 }
7481
7482 // Collect the types that will replace the privatizable type in the function
7483 // signature.
7484 SmallVector<Type *, 16> ReplacementTypes;
7485 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7486
7487 // Verify callee and caller agree on how the promoted argument would be
7488 // passed.
7489 Function &Fn = *getIRPosition().getAnchorScope();
7490 const auto *TTI =
7491 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
7492 if (!TTI) {
7493 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
7494 << Fn.getName() << "\n");
7495 return indicatePessimisticFixpoint();
7496 }
7497
7498 auto CallSiteCheck = [&](AbstractCallSite ACS) {
7499 CallBase *CB = ACS.getInstruction();
7500 return TTI->areTypesABICompatible(
7501 CB->getCaller(),
7503 ReplacementTypes);
7504 };
7505 bool UsedAssumedInformation = false;
7506 if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
7507 UsedAssumedInformation)) {
7508 LLVM_DEBUG(
7509 dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
7510 << Fn.getName() << "\n");
7511 return indicatePessimisticFixpoint();
7512 }
7513
7514 // Register a rewrite of the argument.
7515 Argument *Arg = getAssociatedArgument();
7516 if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
7517 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
7518 return indicatePessimisticFixpoint();
7519 }
7520
7521 unsigned ArgNo = Arg->getArgNo();
7522
7523 // Helper to check if for the given call site the associated argument is
7524 // passed to a callback where the privatization would be different.
7525 auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
7526 SmallVector<const Use *, 4> CallbackUses;
7527 AbstractCallSite::getCallbackUses(CB, CallbackUses);
7528 for (const Use *U : CallbackUses) {
7529 AbstractCallSite CBACS(U);
7530 assert(CBACS && CBACS.isCallbackCall());
7531 for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
7532 int CBArgNo = CBACS.getCallArgOperandNo(CBArg);
7533
7534 LLVM_DEBUG({
7535 dbgs()
7536 << "[AAPrivatizablePtr] Argument " << *Arg
7537 << "check if can be privatized in the context of its parent ("
7538 << Arg->getParent()->getName()
7539 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7540 "callback ("
7541 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7542 << ")\n[AAPrivatizablePtr] " << CBArg << " : "
7543 << CBACS.getCallArgOperand(CBArg) << " vs "
7544 << CB.getArgOperand(ArgNo) << "\n"
7545 << "[AAPrivatizablePtr] " << CBArg << " : "
7546 << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
7547 });
7548
7549 if (CBArgNo != int(ArgNo))
7550 continue;
7551 const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7552 *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
7553 if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
7554 auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
7555 if (!CBArgPrivTy)
7556 continue;
7557 if (*CBArgPrivTy == PrivatizableType)
7558 continue;
7559 }
7560
7561 LLVM_DEBUG({
7562 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7563 << " cannot be privatized in the context of its parent ("
7564 << Arg->getParent()->getName()
7565 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7566 "callback ("
7567 << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
7568 << ").\n[AAPrivatizablePtr] for which the argument "
7569 "privatization is not compatible.\n";
7570 });
7571 return false;
7572 }
7573 }
7574 return true;
7575 };
7576
7577 // Helper to check if for the given call site the associated argument is
7578 // passed to a direct call where the privatization would be different.
7579 auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
7580 CallBase *DC = cast<CallBase>(ACS.getInstruction());
7581 int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
7582 assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
7583 "Expected a direct call operand for callback call operand");
7584
7585 Function *DCCallee =
7587 LLVM_DEBUG({
7588 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7589 << " check if be privatized in the context of its parent ("
7590 << Arg->getParent()->getName()
7591 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7592 "direct call of ("
7593 << DCArgNo << "@" << DCCallee->getName() << ").\n";
7594 });
7595
7596 if (unsigned(DCArgNo) < DCCallee->arg_size()) {
7597 const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
7598 *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
7599 DepClassTy::REQUIRED);
7600 if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
7601 auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
7602 if (!DCArgPrivTy)
7603 return true;
7604 if (*DCArgPrivTy == PrivatizableType)
7605 return true;
7606 }
7607 }
7608
7609 LLVM_DEBUG({
7610 dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
7611 << " cannot be privatized in the context of its parent ("
7612 << Arg->getParent()->getName()
7613 << ")\n[AAPrivatizablePtr] because it is an argument in a "
7614 "direct call of ("
7616 << ").\n[AAPrivatizablePtr] for which the argument "
7617 "privatization is not compatible.\n";
7618 });
7619 return false;
7620 };
7621
7622 // Helper to check if the associated argument is used at the given abstract
7623 // call site in a way that is incompatible with the privatization assumed
7624 // here.
7625 auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
7626 if (ACS.isDirectCall())
7627 return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
7628 if (ACS.isCallbackCall())
7629 return IsCompatiblePrivArgOfDirectCS(ACS);
7630 return false;
7631 };
7632
7633 if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
7634 UsedAssumedInformation))
7635 return indicatePessimisticFixpoint();
7636
7637 return ChangeStatus::UNCHANGED;
7638 }
7639
7640 /// Given a type to private \p PrivType, collect the constituates (which are
7641 /// used) in \p ReplacementTypes.
7642 static void
7643 identifyReplacementTypes(Type *PrivType,
7644 SmallVectorImpl<Type *> &ReplacementTypes) {
7645 // TODO: For now we expand the privatization type to the fullest which can
7646 // lead to dead arguments that need to be removed later.
7647 assert(PrivType && "Expected privatizable type!");
7648
7649 // Traverse the type, extract constituate types on the outermost level.
7650 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7651 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
7652 ReplacementTypes.push_back(PrivStructType->getElementType(u));
7653 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7654 ReplacementTypes.append(PrivArrayType->getNumElements(),
7655 PrivArrayType->getElementType());
7656 } else {
7657 ReplacementTypes.push_back(PrivType);
7658 }
7659 }
7660
7661 /// Initialize \p Base according to the type \p PrivType at position \p IP.
7662 /// The values needed are taken from the arguments of \p F starting at
7663 /// position \p ArgNo.
7664 static void createInitialization(Type *PrivType, Value &Base, Function &F,
7665 unsigned ArgNo, BasicBlock::iterator IP) {
7666 assert(PrivType && "Expected privatizable type!");
7667
7668 IRBuilder<NoFolder> IRB(IP);
7669 const DataLayout &DL = F.getDataLayout();
7670
7671 // Traverse the type, build GEPs and stores.
7672 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7673 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7674 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7675 Value *Ptr =
7676 constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
7677 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7678 }
7679 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7680 Type *PointeeTy = PrivArrayType->getElementType();
7681 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7682 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7683 Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
7684 new StoreInst(F.getArg(ArgNo + u), Ptr, IP);
7685 }
7686 } else {
7687 new StoreInst(F.getArg(ArgNo), &Base, IP);
7688 }
7689 }
7690
7691 /// Extract values from \p Base according to the type \p PrivType at the
7692 /// call position \p ACS. The values are appended to \p ReplacementValues.
7693 void createReplacementValues(Align Alignment, Type *PrivType,
7694 AbstractCallSite ACS, Value *Base,
7695 SmallVectorImpl<Value *> &ReplacementValues) {
7696 assert(Base && "Expected base value!");
7697 assert(PrivType && "Expected privatizable type!");
7698 Instruction *IP = ACS.getInstruction();
7699
7700 IRBuilder<NoFolder> IRB(IP);
7701 const DataLayout &DL = IP->getDataLayout();
7702
7703 // Traverse the type, build GEPs and loads.
7704 if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
7705 const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
7706 for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
7707 Type *PointeeTy = PrivStructType->getElementType(u);
7708 Value *Ptr =
7709 constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
7710 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7711 L->setAlignment(Alignment);
7712 ReplacementValues.push_back(L);
7713 }
7714 } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
7715 Type *PointeeTy = PrivArrayType->getElementType();
7716 uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
7717 for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
7718 Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
7719 LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP->getIterator());
7720 L->setAlignment(Alignment);
7721 ReplacementValues.push_back(L);
7722 }
7723 } else {
7724 LoadInst *L = new LoadInst(PrivType, Base, "", IP->getIterator());
7725 L->setAlignment(Alignment);
7726 ReplacementValues.push_back(L);
7727 }
7728 }
7729
7730 /// See AbstractAttribute::manifest(...)
7731 ChangeStatus manifest(Attributor &A) override {
7732 if (!PrivatizableType)
7733 return ChangeStatus::UNCHANGED;
7734 assert(*PrivatizableType && "Expected privatizable type!");
7735
7736 // Collect all tail calls in the function as we cannot allow new allocas to
7737 // escape into tail recursion.
7738 // TODO: Be smarter about new allocas escaping into tail calls.
7740 bool UsedAssumedInformation = false;
7741 if (!A.checkForAllInstructions(
7742 [&](Instruction &I) {
7743 CallInst &CI = cast<CallInst>(I);
7744 if (CI.isTailCall())
7745 TailCalls.push_back(&CI);
7746 return true;
7747 },
7748 *this, {Instruction::Call}, UsedAssumedInformation))
7749 return ChangeStatus::UNCHANGED;
7750
7751 Argument *Arg = getAssociatedArgument();
7752 // Query AAAlign attribute for alignment of associated argument to
7753 // determine the best alignment of loads.
7754 const auto *AlignAA =
7755 A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);
7756
7757 // Callback to repair the associated function. A new alloca is placed at the
7758 // beginning and initialized with the values passed through arguments. The
7759 // new alloca replaces the use of the old pointer argument.
7761 [=](const Attributor::ArgumentReplacementInfo &ARI,
7762 Function &ReplacementFn, Function::arg_iterator ArgIt) {
7763 BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
7765 const DataLayout &DL = IP->getDataLayout();
7766 unsigned AS = DL.getAllocaAddrSpace();
7767 Instruction *AI = new AllocaInst(*PrivatizableType, AS,
7768 Arg->getName() + ".priv", IP);
7769 createInitialization(*PrivatizableType, *AI, ReplacementFn,
7770 ArgIt->getArgNo(), IP);
7771
7772 if (AI->getType() != Arg->getType())
7773 AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
7774 AI, Arg->getType(), "", IP);
7775 Arg->replaceAllUsesWith(AI);
7776
7777 for (CallInst *CI : TailCalls)
7778 CI->setTailCall(false);
7779 };
7780
7781 // Callback to repair a call site of the associated function. The elements
7782 // of the privatizable type are loaded prior to the call and passed to the
7783 // new function version.
7785 [=](const Attributor::ArgumentReplacementInfo &ARI,
7786 AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
7787 // When no alignment is specified for the load instruction,
7788 // natural alignment is assumed.
7789 createReplacementValues(
7790 AlignAA ? AlignAA->getAssumedAlign() : Align(0),
7791 *PrivatizableType, ACS,
7792 ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
7793 NewArgOperands);
7794 };
7795
7796 // Collect the types that will replace the privatizable type in the function
7797 // signature.
7798 SmallVector<Type *, 16> ReplacementTypes;
7799 identifyReplacementTypes(*PrivatizableType, ReplacementTypes);
7800
7801 // Register a rewrite of the argument.
7802 if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
7803 std::move(FnRepairCB),
7804 std::move(ACSRepairCB)))
7805 return ChangeStatus::CHANGED;
7806 return ChangeStatus::UNCHANGED;
7807 }
7808
7809 /// See AbstractAttribute::trackStatistics()
7810 void trackStatistics() const override {
7811 STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
7812 }
7813};
7814
7815struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
7816 AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
7817 : AAPrivatizablePtrImpl(IRP, A) {}
7818
7819 /// See AbstractAttribute::initialize(...).
7820 void initialize(Attributor &A) override {
7821 // TODO: We can privatize more than arguments.
7822 indicatePessimisticFixpoint();
7823 }
7824
7825 ChangeStatus updateImpl(Attributor &A) override {
7826 llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
7827 "updateImpl will not be called");
7828 }
7829
7830 /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
7831 std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
7832 Value *Obj = getUnderlyingObject(&getAssociatedValue());
7833 if (!Obj) {
7834 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
7835 return nullptr;
7836 }
7837
7838 if (auto *AI = dyn_cast<AllocaInst>(Obj))
7839 if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
7840 if (CI->isOne())
7841 return AI->getAllocatedType();
7842 if (auto *Arg = dyn_cast<Argument>(Obj)) {
7843 auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
7844 *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
7845 if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
7846 return PrivArgAA->getPrivatizableType();
7847 }
7848
7849 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
7850 "alloca nor privatizable argument: "
7851 << *Obj << "!\n");
7852 return nullptr;
7853 }
7854
7855 /// See AbstractAttribute::trackStatistics()
7856 void trackStatistics() const override {
7857 STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
7858 }
7859};
7860
7861struct AAPrivatizablePtrCallSiteArgument final
7862 : public AAPrivatizablePtrFloating {
7863 AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
7864 : AAPrivatizablePtrFloating(IRP, A) {}
7865
7866 /// See AbstractAttribute::initialize(...).
7867 void initialize(Attributor &A) override {
7868 if (A.hasAttr(getIRPosition(), Attribute::ByVal))
7869 indicateOptimisticFixpoint();
7870 }
7871
7872 /// See AbstractAttribute::updateImpl(...).
7873 ChangeStatus updateImpl(Attributor &A) override {
7874 PrivatizableType = identifyPrivatizableType(A);
7875 if (!PrivatizableType)
7876 return ChangeStatus::UNCHANGED;
7877 if (!*PrivatizableType)
7878 return indicatePessimisticFixpoint();
7879
7880 const IRPosition &IRP = getIRPosition();
7881 bool IsKnownNoCapture;
7882 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
7883 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
7884 if (!IsAssumedNoCapture) {
7885 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
7886 return indicatePessimisticFixpoint();
7887 }
7888
7889 bool IsKnownNoAlias;
7891 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
7892 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
7893 return indicatePessimisticFixpoint();
7894 }
7895
7896 bool IsKnown;
7897 if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
7898 LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
7899 return indicatePessimisticFixpoint();
7900 }
7901
7902 return ChangeStatus::UNCHANGED;
7903 }
7904
7905 /// See AbstractAttribute::trackStatistics()
7906 void trackStatistics() const override {
7907 STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
7908 }
7909};
7910
7911struct AAPrivatizablePtrCallSiteReturned final
7912 : public AAPrivatizablePtrFloating {
7913 AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
7914 : AAPrivatizablePtrFloating(IRP, A) {}
7915
7916 /// See AbstractAttribute::initialize(...).
7917 void initialize(Attributor &A) override {
7918 // TODO: We can privatize more than arguments.
7919 indicatePessimisticFixpoint();
7920 }
7921
7922 /// See AbstractAttribute::trackStatistics()
7923 void trackStatistics() const override {
7924 STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
7925 }
7926};
7927
7928struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
7929 AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
7930 : AAPrivatizablePtrFloating(IRP, A) {}
7931
7932 /// See AbstractAttribute::initialize(...).
7933 void initialize(Attributor &A) override {
7934 // TODO: We can privatize more than arguments.
7935 indicatePessimisticFixpoint();
7936 }
7937
7938 /// See AbstractAttribute::trackStatistics()
7939 void trackStatistics() const override {
7940 STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
7941 }
7942};
7943} // namespace
7944
7945/// -------------------- Memory Behavior Attributes ----------------------------
7946/// Includes read-none, read-only, and write-only.
7947/// ----------------------------------------------------------------------------
7948namespace {
7949struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
7950 AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
7951 : AAMemoryBehavior(IRP, A) {}
7952
7953 /// See AbstractAttribute::initialize(...).
7954 void initialize(Attributor &A) override {
7955 intersectAssumedBits(BEST_STATE);
7956 getKnownStateFromValue(A, getIRPosition(), getState());
7957 AAMemoryBehavior::initialize(A);
7958 }
7959
7960 /// Return the memory behavior information encoded in the IR for \p IRP.
7961 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
7962 BitIntegerState &State,
7963 bool IgnoreSubsumingPositions = false) {
7965 A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
7966 for (const Attribute &Attr : Attrs) {
7967 switch (Attr.getKindAsEnum()) {
7968 case Attribute::ReadNone:
7969 State.addKnownBits(NO_ACCESSES);
7970 break;
7971 case Attribute::ReadOnly:
7972 State.addKnownBits(NO_WRITES);
7973 break;
7974 case Attribute::WriteOnly:
7975 State.addKnownBits(NO_READS);
7976 break;
7977 default:
7978 llvm_unreachable("Unexpected attribute!");
7979 }
7980 }
7981
7982 if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
7983 if (!I->mayReadFromMemory())
7984 State.addKnownBits(NO_READS);
7985 if (!I->mayWriteToMemory())
7986 State.addKnownBits(NO_WRITES);
7987 }
7988 }
7989
7990 /// See AbstractAttribute::getDeducedAttributes(...).
7991 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
7992 SmallVectorImpl<Attribute> &Attrs) const override {
7993 assert(Attrs.size() == 0);
7994 if (isAssumedReadNone())
7995 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
7996 else if (isAssumedReadOnly())
7997 Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
7998 else if (isAssumedWriteOnly())
7999 Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
8000 assert(Attrs.size() <= 1);
8001 }
8002
8003 /// See AbstractAttribute::manifest(...).
8004 ChangeStatus manifest(Attributor &A) override {
8005 const IRPosition &IRP = getIRPosition();
8006
8007 if (A.hasAttr(IRP, Attribute::ReadNone,
8008 /* IgnoreSubsumingPositions */ true))
8009 return ChangeStatus::UNCHANGED;
8010
8011 // Check if we would improve the existing attributes first.
8012 SmallVector<Attribute, 4> DeducedAttrs;
8013 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8014 if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
8015 return A.hasAttr(IRP, Attr.getKindAsEnum(),
8016 /* IgnoreSubsumingPositions */ true);
8017 }))
8018 return ChangeStatus::UNCHANGED;
8019
8020 // Clear existing attributes.
8021 A.removeAttrs(IRP, AttrKinds);
8022 // Clear conflicting writable attribute.
8023 if (isAssumedReadOnly())
8024 A.removeAttrs(IRP, Attribute::Writable);
8025
8026 // Use the generic manifest method.
8027 return IRAttribute::manifest(A);
8028 }
8029
8030 /// See AbstractState::getAsStr().
8031 const std::string getAsStr(Attributor *A) const override {
8032 if (isAssumedReadNone())
8033 return "readnone";
8034 if (isAssumedReadOnly())
8035 return "readonly";
8036 if (isAssumedWriteOnly())
8037 return "writeonly";
8038 return "may-read/write";
8039 }
8040
8041 /// The set of IR attributes AAMemoryBehavior deals with.
8042 static const Attribute::AttrKind AttrKinds[3];
8043};
8044
8045const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
8046 Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};
8047
8048/// Memory behavior attribute for a floating value.
8049struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
8050 AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
8051 : AAMemoryBehaviorImpl(IRP, A) {}
8052
8053 /// See AbstractAttribute::updateImpl(...).
8054 ChangeStatus updateImpl(Attributor &A) override;
8055
8056 /// See AbstractAttribute::trackStatistics()
8057 void trackStatistics() const override {
8058 if (isAssumedReadNone())
8060 else if (isAssumedReadOnly())
8062 else if (isAssumedWriteOnly())
8064 }
8065
8066private:
8067 /// Return true if users of \p UserI might access the underlying
8068 /// variable/location described by \p U and should therefore be analyzed.
8069 bool followUsersOfUseIn(Attributor &A, const Use &U,
8070 const Instruction *UserI);
8071
8072 /// Update the state according to the effect of use \p U in \p UserI.
8073 void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
8074};
8075
8076/// Memory behavior attribute for function argument.
8077struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
8078 AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
8079 : AAMemoryBehaviorFloating(IRP, A) {}
8080
8081 /// See AbstractAttribute::initialize(...).
8082 void initialize(Attributor &A) override {
8083 intersectAssumedBits(BEST_STATE);
8084 const IRPosition &IRP = getIRPosition();
8085 // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
8086 // can query it when we use has/getAttr. That would allow us to reuse the
8087 // initialize of the base class here.
8088 bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
8089 /* IgnoreSubsumingPositions */ true);
8090 getKnownStateFromValue(A, IRP, getState(),
8091 /* IgnoreSubsumingPositions */ HasByVal);
8092 }
8093
8094 ChangeStatus manifest(Attributor &A) override {
8095 // TODO: Pointer arguments are not supported on vectors of pointers yet.
8096 if (!getAssociatedValue().getType()->isPointerTy())
8097 return ChangeStatus::UNCHANGED;
8098
8099 // TODO: From readattrs.ll: "inalloca parameters are always
8100 // considered written"
8101 if (A.hasAttr(getIRPosition(),
8102 {Attribute::InAlloca, Attribute::Preallocated})) {
8103 removeKnownBits(NO_WRITES);
8104 removeAssumedBits(NO_WRITES);
8105 }
8106 A.removeAttrs(getIRPosition(), AttrKinds);
8107 return AAMemoryBehaviorFloating::manifest(A);
8108 }
8109
8110 /// See AbstractAttribute::trackStatistics()
8111 void trackStatistics() const override {
8112 if (isAssumedReadNone())
8113 STATS_DECLTRACK_ARG_ATTR(readnone)
8114 else if (isAssumedReadOnly())
8115 STATS_DECLTRACK_ARG_ATTR(readonly)
8116 else if (isAssumedWriteOnly())
8117 STATS_DECLTRACK_ARG_ATTR(writeonly)
8118 }
8119};
8120
8121struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
8122 AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
8123 : AAMemoryBehaviorArgument(IRP, A) {}
8124
8125 /// See AbstractAttribute::initialize(...).
8126 void initialize(Attributor &A) override {
8127 // If we don't have an associated attribute this is either a variadic call
8128 // or an indirect call, either way, nothing to do here.
8129 Argument *Arg = getAssociatedArgument();
8130 if (!Arg) {
8131 indicatePessimisticFixpoint();
8132 return;
8133 }
8134 if (Arg->hasByValAttr()) {
8135 addKnownBits(NO_WRITES);
8136 removeKnownBits(NO_READS);
8137 removeAssumedBits(NO_READS);
8138 }
8139 AAMemoryBehaviorArgument::initialize(A);
8140 if (getAssociatedFunction()->isDeclaration())
8141 indicatePessimisticFixpoint();
8142 }
8143
8144 /// See AbstractAttribute::updateImpl(...).
8145 ChangeStatus updateImpl(Attributor &A) override {
8146 // TODO: Once we have call site specific value information we can provide
8147 // call site specific liveness liveness information and then it makes
8148 // sense to specialize attributes for call sites arguments instead of
8149 // redirecting requests to the callee argument.
8150 Argument *Arg = getAssociatedArgument();
8151 const IRPosition &ArgPos = IRPosition::argument(*Arg);
8152 auto *ArgAA =
8153 A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
8154 if (!ArgAA)
8155 return indicatePessimisticFixpoint();
8156 return clampStateAndIndicateChange(getState(), ArgAA->getState());
8157 }
8158
8159 /// See AbstractAttribute::trackStatistics()
8160 void trackStatistics() const override {
8161 if (isAssumedReadNone())
8163 else if (isAssumedReadOnly())
8165 else if (isAssumedWriteOnly())
8167 }
8168};
8169
8170/// Memory behavior attribute for a call site return position.
8171struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
8172 AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
8173 : AAMemoryBehaviorFloating(IRP, A) {}
8174
8175 /// See AbstractAttribute::initialize(...).
8176 void initialize(Attributor &A) override {
8177 AAMemoryBehaviorImpl::initialize(A);
8178 }
8179 /// See AbstractAttribute::manifest(...).
8180 ChangeStatus manifest(Attributor &A) override {
8181 // We do not annotate returned values.
8182 return ChangeStatus::UNCHANGED;
8183 }
8184
8185 /// See AbstractAttribute::trackStatistics()
8186 void trackStatistics() const override {}
8187};
8188
8189/// An AA to represent the memory behavior function attributes.
8190struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
8191 AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
8192 : AAMemoryBehaviorImpl(IRP, A) {}
8193
8194 /// See AbstractAttribute::updateImpl(Attributor &A).
8195 ChangeStatus updateImpl(Attributor &A) override;
8196
8197 /// See AbstractAttribute::manifest(...).
8198 ChangeStatus manifest(Attributor &A) override {
8199 // TODO: It would be better to merge this with AAMemoryLocation, so that
8200 // we could determine read/write per location. This would also have the
8201 // benefit of only one place trying to manifest the memory attribute.
8202 Function &F = cast<Function>(getAnchorValue());
8204 if (isAssumedReadNone())
8205 ME = MemoryEffects::none();
8206 else if (isAssumedReadOnly())
8208 else if (isAssumedWriteOnly())
8210
8211 A.removeAttrs(getIRPosition(), AttrKinds);
8212 // Clear conflicting writable attribute.
8213 if (ME.onlyReadsMemory())
8214 for (Argument &Arg : F.args())
8215 A.removeAttrs(IRPosition::argument(Arg), Attribute::Writable);
8216 return A.manifestAttrs(getIRPosition(),
8217 Attribute::getWithMemoryEffects(F.getContext(), ME));
8218 }
8219
8220 /// See AbstractAttribute::trackStatistics()
8221 void trackStatistics() const override {
8222 if (isAssumedReadNone())
8223 STATS_DECLTRACK_FN_ATTR(readnone)
8224 else if (isAssumedReadOnly())
8225 STATS_DECLTRACK_FN_ATTR(readonly)
8226 else if (isAssumedWriteOnly())
8227 STATS_DECLTRACK_FN_ATTR(writeonly)
8228 }
8229};
8230
8231/// AAMemoryBehavior attribute for call sites.
8232struct AAMemoryBehaviorCallSite final
8233 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {
8234 AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
8235 : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl>(IRP, A) {}
8236
8237 /// See AbstractAttribute::manifest(...).
8238 ChangeStatus manifest(Attributor &A) override {
8239 // TODO: Deduplicate this with AAMemoryBehaviorFunction.
8240 CallBase &CB = cast<CallBase>(getAnchorValue());
8242 if (isAssumedReadNone())
8243 ME = MemoryEffects::none();
8244 else if (isAssumedReadOnly())
8246 else if (isAssumedWriteOnly())
8248
8249 A.removeAttrs(getIRPosition(), AttrKinds);
8250 // Clear conflicting writable attribute.
8251 if (ME.onlyReadsMemory())
8252 for (Use &U : CB.args())
8253 A.removeAttrs(IRPosition::callsite_argument(CB, U.getOperandNo()),
8254 Attribute::Writable);
8255 return A.manifestAttrs(
8256 getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
8257 }
8258
8259 /// See AbstractAttribute::trackStatistics()
8260 void trackStatistics() const override {
8261 if (isAssumedReadNone())
8262 STATS_DECLTRACK_CS_ATTR(readnone)
8263 else if (isAssumedReadOnly())
8264 STATS_DECLTRACK_CS_ATTR(readonly)
8265 else if (isAssumedWriteOnly())
8266 STATS_DECLTRACK_CS_ATTR(writeonly)
8267 }
8268};
8269
8270ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {
8271
8272 // The current assumed state used to determine a change.
8273 auto AssumedState = getAssumed();
8274
8275 auto CheckRWInst = [&](Instruction &I) {
8276 // If the instruction has an own memory behavior state, use it to restrict
8277 // the local state. No further analysis is required as the other memory
8278 // state is as optimistic as it gets.
8279 if (const auto *CB = dyn_cast<CallBase>(&I)) {
8280 const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
8282 if (MemBehaviorAA) {
8283 intersectAssumedBits(MemBehaviorAA->getAssumed());
8284 return !isAtFixpoint();
8285 }
8286 }
8287
8288 // Remove access kind modifiers if necessary.
8289 if (I.mayReadFromMemory())
8290 removeAssumedBits(NO_READS);
8291 if (I.mayWriteToMemory())
8292 removeAssumedBits(NO_WRITES);
8293 return !isAtFixpoint();
8294 };
8295
8296 bool UsedAssumedInformation = false;
8297 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8298 UsedAssumedInformation))
8299 return indicatePessimisticFixpoint();
8300
8301 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8303}
8304
8305ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {
8306
8307 const IRPosition &IRP = getIRPosition();
8308 const IRPosition &FnPos = IRPosition::function_scope(IRP);
8309 AAMemoryBehavior::StateType &S = getState();
8310
8311 // First, check the function scope. We take the known information and we avoid
8312 // work if the assumed information implies the current assumed information for
8313 // this attribute. This is a valid for all but byval arguments.
8314 Argument *Arg = IRP.getAssociatedArgument();
8315 AAMemoryBehavior::base_t FnMemAssumedState =
8317 if (!Arg || !Arg->hasByValAttr()) {
8318 const auto *FnMemAA =
8319 A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
8320 if (FnMemAA) {
8321 FnMemAssumedState = FnMemAA->getAssumed();
8322 S.addKnownBits(FnMemAA->getKnown());
8323 if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
8325 }
8326 }
8327
8328 // The current assumed state used to determine a change.
8329 auto AssumedState = S.getAssumed();
8330
8331 // Make sure the value is not captured (except through "return"), if
8332 // it is, any information derived would be irrelevant anyway as we cannot
8333 // check the potential aliases introduced by the capture. However, no need
8334 // to fall back to anythign less optimistic than the function state.
8335 bool IsKnownNoCapture;
8336 const AANoCapture *ArgNoCaptureAA = nullptr;
8337 bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
8338 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
8339 &ArgNoCaptureAA);
8340
8341 if (!IsAssumedNoCapture &&
8342 (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
8343 S.intersectAssumedBits(FnMemAssumedState);
8344 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8346 }
8347
8348 // Visit and expand uses until all are analyzed or a fixpoint is reached.
8349 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
8350 Instruction *UserI = cast<Instruction>(U.getUser());
8351 LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
8352 << " \n");
8353
8354 // Droppable users, e.g., llvm::assume does not actually perform any action.
8355 if (UserI->isDroppable())
8356 return true;
8357
8358 // Check if the users of UserI should also be visited.
8359 Follow = followUsersOfUseIn(A, U, UserI);
8360
8361 // If UserI might touch memory we analyze the use in detail.
8362 if (UserI->mayReadOrWriteMemory())
8363 analyzeUseIn(A, U, UserI);
8364
8365 return !isAtFixpoint();
8366 };
8367
8368 if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
8369 return indicatePessimisticFixpoint();
8370
8371 return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
8373}
8374
8375bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
8376 const Instruction *UserI) {
8377 // The loaded value is unrelated to the pointer argument, no need to
8378 // follow the users of the load.
8379 if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
8380 return false;
8381
8382 // By default we follow all uses assuming UserI might leak information on U,
8383 // we have special handling for call sites operands though.
8384 const auto *CB = dyn_cast<CallBase>(UserI);
8385 if (!CB || !CB->isArgOperand(&U))
8386 return true;
8387
8388 // If the use is a call argument known not to be captured, the users of
8389 // the call do not need to be visited because they have to be unrelated to
8390 // the input. Note that this check is not trivial even though we disallow
8391 // general capturing of the underlying argument. The reason is that the
8392 // call might the argument "through return", which we allow and for which we
8393 // need to check call users.
8394 if (U.get()->getType()->isPointerTy()) {
8395 unsigned ArgNo = CB->getArgOperandNo(&U);
8396 bool IsKnownNoCapture;
8398 A, this, IRPosition::callsite_argument(*CB, ArgNo),
8399 DepClassTy::OPTIONAL, IsKnownNoCapture);
8400 }
8401
8402 return true;
8403}
8404
8405void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
8406 const Instruction *UserI) {
8407 assert(UserI->mayReadOrWriteMemory());
8408
8409 switch (UserI->getOpcode()) {
8410 default:
8411 // TODO: Handle all atomics and other side-effect operations we know of.
8412 break;
8413 case Instruction::Load:
8414 // Loads cause the NO_READS property to disappear.
8415 removeAssumedBits(NO_READS);
8416 return;
8417
8418 case Instruction::Store:
8419 // Stores cause the NO_WRITES property to disappear if the use is the
8420 // pointer operand. Note that while capturing was taken care of somewhere
8421 // else we need to deal with stores of the value that is not looked through.
8422 if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
8423 removeAssumedBits(NO_WRITES);
8424 else
8425 indicatePessimisticFixpoint();
8426 return;
8427
8428 case Instruction::Call:
8429 case Instruction::CallBr:
8430 case Instruction::Invoke: {
8431 // For call sites we look at the argument memory behavior attribute (this
8432 // could be recursive!) in order to restrict our own state.
8433 const auto *CB = cast<CallBase>(UserI);
8434
8435 // Give up on operand bundles.
8436 if (CB->isBundleOperand(&U)) {
8437 indicatePessimisticFixpoint();
8438 return;
8439 }
8440
8441 // Calling a function does read the function pointer, maybe write it if the
8442 // function is self-modifying.
8443 if (CB->isCallee(&U)) {
8444 removeAssumedBits(NO_READS);
8445 break;
8446 }
8447
8448 // Adjust the possible access behavior based on the information on the
8449 // argument.
8450 IRPosition Pos;
8451 if (U.get()->getType()->isPointerTy())
8453 else
8455 const auto *MemBehaviorAA =
8456 A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
8457 if (!MemBehaviorAA)
8458 break;
8459 // "assumed" has at most the same bits as the MemBehaviorAA assumed
8460 // and at least "known".
8461 intersectAssumedBits(MemBehaviorAA->getAssumed());
8462 return;
8463 }
8464 };
8465
8466 // Generally, look at the "may-properties" and adjust the assumed state if we
8467 // did not trigger special handling before.
8468 if (UserI->mayReadFromMemory())
8469 removeAssumedBits(NO_READS);
8470 if (UserI->mayWriteToMemory())
8471 removeAssumedBits(NO_WRITES);
8472}
8473} // namespace
8474
8475/// -------------------- Memory Locations Attributes ---------------------------
8476/// Includes read-none, argmemonly, inaccessiblememonly,
8477/// inaccessiblememorargmemonly
8478/// ----------------------------------------------------------------------------
8479
8482 if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
8483 return "all memory";
8485 return "no memory";
8486 std::string S = "memory:";
8487 if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
8488 S += "stack,";
8489 if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
8490 S += "constant,";
8492 S += "internal global,";
8494 S += "external global,";
8495 if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
8496 S += "argument,";
8498 S += "inaccessible,";
8499 if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
8500 S += "malloced,";
8501 if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
8502 S += "unknown,";
8503 S.pop_back();
8504 return S;
8505}
8506
8507namespace {
8508struct AAMemoryLocationImpl : public AAMemoryLocation {
8509
8510 AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
8511 : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
8512 AccessKind2Accesses.fill(nullptr);
8513 }
8514
8515 ~AAMemoryLocationImpl() override {
8516 // The AccessSets are allocated via a BumpPtrAllocator, we call
8517 // the destructor manually.
8518 for (AccessSet *AS : AccessKind2Accesses)
8519 if (AS)
8520 AS->~AccessSet();
8521 }
8522
8523 /// See AbstractAttribute::initialize(...).
8524 void initialize(Attributor &A) override {
8525 intersectAssumedBits(BEST_STATE);
8526 getKnownStateFromValue(A, getIRPosition(), getState());
8527 AAMemoryLocation::initialize(A);
8528 }
8529
8530 /// Return the memory behavior information encoded in the IR for \p IRP.
8531 static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
8532 BitIntegerState &State,
8533 bool IgnoreSubsumingPositions = false) {
8534 // For internal functions we ignore `argmemonly` and
8535 // `inaccessiblememorargmemonly` as we might break it via interprocedural
8536 // constant propagation. It is unclear if this is the best way but it is
8537 // unlikely this will cause real performance problems. If we are deriving
8538 // attributes for the anchor function we even remove the attribute in
8539 // addition to ignoring it.
8540 // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
8541 // MemoryEffects::Other as a possible location.
8542 bool UseArgMemOnly = true;
8543 Function *AnchorFn = IRP.getAnchorScope();
8544 if (AnchorFn && A.isRunOn(*AnchorFn))
8545 UseArgMemOnly = !AnchorFn->hasLocalLinkage();
8546
8548 A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
8549 for (const Attribute &Attr : Attrs) {
8550 // TODO: We can map MemoryEffects to Attributor locations more precisely.
8551 MemoryEffects ME = Attr.getMemoryEffects();
8552 if (ME.doesNotAccessMemory()) {
8553 State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
8554 continue;
8555 }
8556 if (ME.onlyAccessesInaccessibleMem()) {
8557 State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
8558 continue;
8559 }
8560 if (ME.onlyAccessesArgPointees()) {
8561 if (UseArgMemOnly)
8562 State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
8563 else {
8564 // Remove location information, only keep read/write info.
8565 ME = MemoryEffects(ME.getModRef());
8566 A.manifestAttrs(IRP,
8567 Attribute::getWithMemoryEffects(
8568 IRP.getAnchorValue().getContext(), ME),
8569 /*ForceReplace*/ true);
8570 }
8571 continue;
8572 }
8574 if (UseArgMemOnly)
8575 State.addKnownBits(inverseLocation(
8576 NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
8577 else {
8578 // Remove location information, only keep read/write info.
8579 ME = MemoryEffects(ME.getModRef());
8580 A.manifestAttrs(IRP,
8581 Attribute::getWithMemoryEffects(
8582 IRP.getAnchorValue().getContext(), ME),
8583 /*ForceReplace*/ true);
8584 }
8585 continue;
8586 }
8587 }
8588 }
8589
8590 /// See AbstractAttribute::getDeducedAttributes(...).
8591 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
8592 SmallVectorImpl<Attribute> &Attrs) const override {
8593 // TODO: We can map Attributor locations to MemoryEffects more precisely.
8594 assert(Attrs.size() == 0);
8595 if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
8596 if (isAssumedReadNone())
8597 Attrs.push_back(
8598 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
8599 else if (isAssumedInaccessibleMemOnly())
8600 Attrs.push_back(Attribute::getWithMemoryEffects(
8602 else if (isAssumedArgMemOnly())
8603 Attrs.push_back(
8604 Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
8605 else if (isAssumedInaccessibleOrArgMemOnly())
8606 Attrs.push_back(Attribute::getWithMemoryEffects(
8608 }
8609 assert(Attrs.size() <= 1);
8610 }
8611
8612 /// See AbstractAttribute::manifest(...).
8613 ChangeStatus manifest(Attributor &A) override {
8614 // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
8615 // provide per-location modref information here.
8616 const IRPosition &IRP = getIRPosition();
8617
8618 SmallVector<Attribute, 1> DeducedAttrs;
8619 getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
8620 if (DeducedAttrs.size() != 1)
8621 return ChangeStatus::UNCHANGED;
8622 MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();
8623
8624 return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
8625 IRP.getAnchorValue().getContext(), ME));
8626 }
8627
8628 /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
8629 bool checkForAllAccessesToMemoryKind(
8630 function_ref<bool(const Instruction *, const Value *, AccessKind,
8631 MemoryLocationsKind)>
8632 Pred,
8633 MemoryLocationsKind RequestedMLK) const override {
8634 if (!isValidState())
8635 return false;
8636
8637 MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
8638 if (AssumedMLK == NO_LOCATIONS)
8639 return true;
8640
8641 unsigned Idx = 0;
8642 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
8643 CurMLK *= 2, ++Idx) {
8644 if (CurMLK & RequestedMLK)
8645 continue;
8646
8647 if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
8648 for (const AccessInfo &AI : *Accesses)
8649 if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
8650 return false;
8651 }
8652
8653 return true;
8654 }
8655
8656 ChangeStatus indicatePessimisticFixpoint() override {
8657 // If we give up and indicate a pessimistic fixpoint this instruction will
8658 // become an access for all potential access kinds:
8659 // TODO: Add pointers for argmemonly and globals to improve the results of
8660 // checkForAllAccessesToMemoryKind.
8661 bool Changed = false;
8662 MemoryLocationsKind KnownMLK = getKnown();
8663 Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
8664 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
8665 if (!(CurMLK & KnownMLK))
8666 updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
8667 getAccessKindFromInst(I));
8668 return AAMemoryLocation::indicatePessimisticFixpoint();
8669 }
8670
8671protected:
8672 /// Helper struct to tie together an instruction that has a read or write
8673 /// effect with the pointer it accesses (if any).
8674 struct AccessInfo {
8675
8676 /// The instruction that caused the access.
8677 const Instruction *I;
8678
8679 /// The base pointer that is accessed, or null if unknown.
8680 const Value *Ptr;
8681
8682 /// The kind of access (read/write/read+write).
8684
8685 bool operator==(const AccessInfo &RHS) const {
8686 return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
8687 }
8688 bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
8689 if (LHS.I != RHS.I)
8690 return LHS.I < RHS.I;
8691 if (LHS.Ptr != RHS.Ptr)
8692 return LHS.Ptr < RHS.Ptr;
8693 if (LHS.Kind != RHS.Kind)
8694 return LHS.Kind < RHS.Kind;
8695 return false;
8696 }
8697 };
8698
8699 /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
8700 /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
8701 using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
8702 std::array<AccessSet *, llvm::ConstantLog2<VALID_STATE>()>
8703 AccessKind2Accesses;
8704
8705 /// Categorize the pointer arguments of CB that might access memory in
8706 /// AccessedLoc and update the state and access map accordingly.
8707 void
8708 categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
8709 AAMemoryLocation::StateType &AccessedLocs,
8710 bool &Changed);
8711
8712 /// Return the kind(s) of location that may be accessed by \p V.
8714 categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);
8715
8716 /// Return the access kind as determined by \p I.
8717 AccessKind getAccessKindFromInst(const Instruction *I) {
8718 AccessKind AK = READ_WRITE;
8719 if (I) {
8720 AK = I->mayReadFromMemory() ? READ : NONE;
8721 AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
8722 }
8723 return AK;
8724 }
8725
8726 /// Update the state \p State and the AccessKind2Accesses given that \p I is
8727 /// an access of kind \p AK to a \p MLK memory location with the access
8728 /// pointer \p Ptr.
8729 void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
8730 MemoryLocationsKind MLK, const Instruction *I,
8731 const Value *Ptr, bool &Changed,
8732 AccessKind AK = READ_WRITE) {
8733
8734 assert(isPowerOf2_32(MLK) && "Expected a single location set!");
8735 auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
8736 if (!Accesses)
8737 Accesses = new (Allocator) AccessSet();
8738 Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
8739 if (MLK == NO_UNKOWN_MEM)
8740 MLK = NO_LOCATIONS;
8741 State.removeAssumedBits(MLK);
8742 }
8743
8744 /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
8745 /// arguments, and update the state and access map accordingly.
8746 void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
8747 AAMemoryLocation::StateType &State, bool &Changed,
8748 unsigned AccessAS = 0);
8749
8750 /// Used to allocate access sets.
8752};
8753
8754void AAMemoryLocationImpl::categorizePtrValue(
8755 Attributor &A, const Instruction &I, const Value &Ptr,
8756 AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
8757 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
8758 << Ptr << " ["
8759 << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");
8760
8761 auto Pred = [&](Value &Obj) {
8762 unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
8763 // TODO: recognize the TBAA used for constant accesses.
8764 MemoryLocationsKind MLK = NO_LOCATIONS;
8765
8766 // Filter accesses to constant (GPU) memory if we have an AS at the access
8767 // site or the object is known to actually have the associated AS.
8768 if (AA::isGPU(A.getModule())) {
8769 if (AA::isGPUConstantAddressSpace(A.getModule(), AccessAS) ||
8770 (AA::isGPUConstantAddressSpace(A.getModule(), ObjectAS) &&
8771 isIdentifiedObject(&Obj)))
8772 return true;
8773 }
8774
8775 if (isa<UndefValue>(&Obj))
8776 return true;
8777 if (isa<Argument>(&Obj)) {
8778 // TODO: For now we do not treat byval arguments as local copies performed
8779 // on the call edge, though, we should. To make that happen we need to
8780 // teach various passes, e.g., DSE, about the copy effect of a byval. That
8781 // would also allow us to mark functions only accessing byval arguments as
8782 // readnone again, arguably their accesses have no effect outside of the
8783 // function, like accesses to allocas.
8784 MLK = NO_ARGUMENT_MEM;
8785 } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
8786 // Reading constant memory is not treated as a read "effect" by the
8787 // function attr pass so we won't neither. Constants defined by TBAA are
8788 // similar. (We know we do not write it because it is constant.)
8789 if (auto *GVar = dyn_cast<GlobalVariable>(GV))
8790 if (GVar->isConstant())
8791 return true;
8792
8793 if (GV->hasLocalLinkage())
8794 MLK = NO_GLOBAL_INTERNAL_MEM;
8795 else
8796 MLK = NO_GLOBAL_EXTERNAL_MEM;
8797 } else if (isa<ConstantPointerNull>(&Obj) &&
8798 (!NullPointerIsDefined(getAssociatedFunction(), AccessAS) ||
8799 !NullPointerIsDefined(getAssociatedFunction(), ObjectAS))) {
8800 return true;
8801 } else if (isa<AllocaInst>(&Obj)) {
8802 MLK = NO_LOCAL_MEM;
8803 } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
8804 bool IsKnownNoAlias;
8807 IsKnownNoAlias))
8808 MLK = NO_MALLOCED_MEM;
8809 else
8810 MLK = NO_UNKOWN_MEM;
8811 } else {
8812 MLK = NO_UNKOWN_MEM;
8813 }
8814
8815 assert(MLK != NO_LOCATIONS && "No location specified!");
8816 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
8817 << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
8818 updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
8819 getAccessKindFromInst(&I));
8820
8821 return true;
8822 };
8823
8824 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
8826 if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
8827 LLVM_DEBUG(
8828 dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
8829 updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
8830 getAccessKindFromInst(&I));
8831 return;
8832 }
8833
8834 LLVM_DEBUG(
8835 dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
8836 << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
8837}
8838
8839void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
8840 Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
8841 bool &Changed) {
8842 for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {
8843
8844 // Skip non-pointer arguments.
8845 const Value *ArgOp = CB.getArgOperand(ArgNo);
8846 if (!ArgOp->getType()->isPtrOrPtrVectorTy())
8847 continue;
8848
8849 // Skip readnone arguments.
8850 const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
8851 const auto *ArgOpMemLocationAA =
8852 A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);
8853
8854 if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
8855 continue;
8856
8857 // Categorize potentially accessed pointer arguments as if there was an
8858 // access instruction with them as pointer.
8859 categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
8860 }
8861}
8862
8864AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
8865 bool &Changed) {
8866 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
8867 << I << "\n");
8868
8869 AAMemoryLocation::StateType AccessedLocs;
8870 AccessedLocs.intersectAssumedBits(NO_LOCATIONS);
8871
8872 if (auto *CB = dyn_cast<CallBase>(&I)) {
8873
8874 // First check if we assume any memory is access is visible.
8875 const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
8877 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
8878 << " [" << CBMemLocationAA << "]\n");
8879 if (!CBMemLocationAA) {
8880 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
8881 Changed, getAccessKindFromInst(&I));
8882 return NO_UNKOWN_MEM;
8883 }
8884
8885 if (CBMemLocationAA->isAssumedReadNone())
8886 return NO_LOCATIONS;
8887
8888 if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
8889 updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
8890 Changed, getAccessKindFromInst(&I));
8891 return AccessedLocs.getAssumed();
8892 }
8893
8894 uint32_t CBAssumedNotAccessedLocs =
8895 CBMemLocationAA->getAssumedNotAccessedLocation();
8896
8897 // Set the argmemonly and global bit as we handle them separately below.
8898 uint32_t CBAssumedNotAccessedLocsNoArgMem =
8899 CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;
8900
8901 for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
8902 if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
8903 continue;
8904 updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
8905 getAccessKindFromInst(&I));
8906 }
8907
8908 // Now handle global memory if it might be accessed. This is slightly tricky
8909 // as NO_GLOBAL_MEM has multiple bits set.
8910 bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
8911 if (HasGlobalAccesses) {
8912 auto AccessPred = [&](const Instruction *, const Value *Ptr,
8913 AccessKind Kind, MemoryLocationsKind MLK) {
8914 updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
8915 getAccessKindFromInst(&I));
8916 return true;
8917 };
8918 if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
8919 AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
8920 return AccessedLocs.getWorstState();
8921 }
8922
8923 LLVM_DEBUG(
8924 dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
8925 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8926
8927 // Now handle argument memory if it might be accessed.
8928 bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
8929 if (HasArgAccesses)
8930 categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);
8931
8932 LLVM_DEBUG(
8933 dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
8934 << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");
8935
8936 return AccessedLocs.getAssumed();
8937 }
8938
8939 if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
8940 LLVM_DEBUG(
8941 dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
8942 << I << " [" << *Ptr << "]\n");
8943 categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
8944 Ptr->getType()->getPointerAddressSpace());
8945 return AccessedLocs.getAssumed();
8946 }
8947
8948 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
8949 << I << "\n");
8950 updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
8951 getAccessKindFromInst(&I));
8952 return AccessedLocs.getAssumed();
8953}
8954
8955/// An AA to represent the memory behavior function attributes.
8956struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
8957 AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
8958 : AAMemoryLocationImpl(IRP, A) {}
8959
8960 /// See AbstractAttribute::updateImpl(Attributor &A).
8961 ChangeStatus updateImpl(Attributor &A) override {
8962
8963 const auto *MemBehaviorAA =
8964 A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
8965 if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
8966 if (MemBehaviorAA->isKnownReadNone())
8967 return indicateOptimisticFixpoint();
8969 "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
8970 A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
8971 return ChangeStatus::UNCHANGED;
8972 }
8973
8974 // The current assumed state used to determine a change.
8975 auto AssumedState = getAssumed();
8976 bool Changed = false;
8977
8978 auto CheckRWInst = [&](Instruction &I) {
8979 MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
8980 LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
8981 << ": " << getMemoryLocationsAsStr(MLK) << "\n");
8982 removeAssumedBits(inverseLocation(MLK, false, false));
8983 // Stop once only the valid bit set in the *not assumed location*, thus
8984 // once we don't actually exclude any memory locations in the state.
8985 return getAssumedNotAccessedLocation() != VALID_STATE;
8986 };
8987
8988 bool UsedAssumedInformation = false;
8989 if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
8990 UsedAssumedInformation))
8991 return indicatePessimisticFixpoint();
8992
8993 Changed |= AssumedState != getAssumed();
8994 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
8995 }
8996
8997 /// See AbstractAttribute::trackStatistics()
8998 void trackStatistics() const override {
8999 if (isAssumedReadNone())
9000 STATS_DECLTRACK_FN_ATTR(readnone)
9001 else if (isAssumedArgMemOnly())
9002 STATS_DECLTRACK_FN_ATTR(argmemonly)
9003 else if (isAssumedInaccessibleMemOnly())
9004 STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
9005 else if (isAssumedInaccessibleOrArgMemOnly())
9006 STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
9007 }
9008};
9009
9010/// AAMemoryLocation attribute for call sites.
9011struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
9012 AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
9013 : AAMemoryLocationImpl(IRP, A) {}
9014
9015 /// See AbstractAttribute::updateImpl(...).
9016 ChangeStatus updateImpl(Attributor &A) override {
9017 // TODO: Once we have call site specific value information we can provide
9018 // call site specific liveness liveness information and then it makes
9019 // sense to specialize attributes for call sites arguments instead of
9020 // redirecting requests to the callee argument.
9021 Function *F = getAssociatedFunction();
9022 const IRPosition &FnPos = IRPosition::function(*F);
9023 auto *FnAA =
9024 A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
9025 if (!FnAA)
9026 return indicatePessimisticFixpoint();
9027 bool Changed = false;
9028 auto AccessPred = [&](const Instruction *I, const Value *Ptr,
9029 AccessKind Kind, MemoryLocationsKind MLK) {
9030 updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
9031 getAccessKindFromInst(I));
9032 return true;
9033 };
9034 if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
9035 return indicatePessimisticFixpoint();
9036 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
9037 }
9038
9039 /// See AbstractAttribute::trackStatistics()
9040 void trackStatistics() const override {
9041 if (isAssumedReadNone())
9042 STATS_DECLTRACK_CS_ATTR(readnone)
9043 }
9044};
9045} // namespace
9046
9047/// ------------------ denormal-fp-math Attribute -------------------------
9048
9049namespace {
9050struct AADenormalFPMathImpl : public AADenormalFPMath {
9051 AADenormalFPMathImpl(const IRPosition &IRP, Attributor &A)
9052 : AADenormalFPMath(IRP, A) {}
9053
9054 const std::string getAsStr(Attributor *A) const override {
9055 std::string Str("AADenormalFPMath[");
9056 raw_string_ostream OS(Str);
9057
9058 DenormalState Known = getKnown();
9059 if (Known.Mode.isValid())
9060 OS << "denormal-fp-math=" << Known.Mode;
9061 else
9062 OS << "invalid";
9063
9064 if (Known.ModeF32.isValid())
9065 OS << " denormal-fp-math-f32=" << Known.ModeF32;
9066 OS << ']';
9067 return Str;
9068 }
9069};
9070
9071struct AADenormalFPMathFunction final : AADenormalFPMathImpl {
9072 AADenormalFPMathFunction(const IRPosition &IRP, Attributor &A)
9073 : AADenormalFPMathImpl(IRP, A) {}
9074
9075 void initialize(Attributor &A) override {
9076 const Function *F = getAnchorScope();
9077 DenormalFPEnv DenormEnv = F->getDenormalFPEnv();
9078
9079 Known = DenormalState{DenormEnv.DefaultMode, DenormEnv.F32Mode};
9080 if (isModeFixed())
9081 indicateFixpoint();
9082 }
9083
9084 ChangeStatus updateImpl(Attributor &A) override {
9085 ChangeStatus Change = ChangeStatus::UNCHANGED;
9086
9087 auto CheckCallSite = [=, &Change, &A](AbstractCallSite CS) {
9088 Function *Caller = CS.getInstruction()->getFunction();
9089 LLVM_DEBUG(dbgs() << "[AADenormalFPMath] Call " << Caller->getName()
9090 << "->" << getAssociatedFunction()->getName() << '\n');
9091
9092 const auto *CallerInfo = A.getAAFor<AADenormalFPMath>(
9093 *this, IRPosition::function(*Caller), DepClassTy::REQUIRED);
9094 if (!CallerInfo)
9095 return false;
9096
9097 Change = Change | clampStateAndIndicateChange(this->getState(),
9098 CallerInfo->getState());
9099 return true;
9100 };
9101
9102 bool AllCallSitesKnown = true;
9103 if (!A.checkForAllCallSites(CheckCallSite, *this, true, AllCallSitesKnown))
9104 return indicatePessimisticFixpoint();
9105
9106 if (Change == ChangeStatus::CHANGED && isModeFixed())
9107 indicateFixpoint();
9108 return Change;
9109 }
9110
9111 ChangeStatus manifest(Attributor &A) override {
9112 LLVMContext &Ctx = getAssociatedFunction()->getContext();
9113
9114 SmallVector<Attribute, 2> AttrToAdd;
9116
9117 // TODO: Change to use DenormalFPEnv everywhere.
9118 DenormalFPEnv KnownEnv(Known.Mode, Known.ModeF32);
9119
9120 if (KnownEnv == DenormalFPEnv::getDefault()) {
9121 AttrToRemove.push_back(Attribute::DenormalFPEnv);
9122 } else {
9123 AttrToAdd.push_back(Attribute::get(
9124 Ctx, Attribute::DenormalFPEnv,
9125 DenormalFPEnv(Known.Mode, Known.ModeF32).toIntValue()));
9126 }
9127
9128 auto &IRP = getIRPosition();
9129
9130 // TODO: There should be a combined add and remove API.
9131 return A.removeAttrs(IRP, AttrToRemove) |
9132 A.manifestAttrs(IRP, AttrToAdd, /*ForceReplace=*/true);
9133 }
9134
9135 void trackStatistics() const override {
9136 STATS_DECLTRACK_FN_ATTR(denormal_fpenv)
9137 }
9138};
9139} // namespace
9140
9141/// ------------------ Value Constant Range Attribute -------------------------
9142
9143namespace {
9144struct AAValueConstantRangeImpl : AAValueConstantRange {
9145 using StateType = IntegerRangeState;
9146 AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
9147 : AAValueConstantRange(IRP, A) {}
9148
9149 /// See AbstractAttribute::initialize(..).
9150 void initialize(Attributor &A) override {
9151 if (A.hasSimplificationCallback(getIRPosition())) {
9152 indicatePessimisticFixpoint();
9153 return;
9154 }
9155
9156 // Intersect a range given by SCEV.
9157 intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));
9158
9159 // Intersect a range given by LVI.
9160 intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
9161 }
9162
9163 /// See AbstractAttribute::getAsStr().
9164 const std::string getAsStr(Attributor *A) const override {
9165 std::string Str;
9166 llvm::raw_string_ostream OS(Str);
9167 OS << "range(" << getBitWidth() << ")<";
9168 getKnown().print(OS);
9169 OS << " / ";
9170 getAssumed().print(OS);
9171 OS << ">";
9172 return Str;
9173 }
9174
9175 /// Helper function to get a SCEV expr for the associated value at program
9176 /// point \p I.
9177 const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
9178 if (!getAnchorScope())
9179 return nullptr;
9180
9181 ScalarEvolution *SE =
9182 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9183 *getAnchorScope());
9184
9185 LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
9186 *getAnchorScope());
9187
9188 if (!SE || !LI)
9189 return nullptr;
9190
9191 const SCEV *S = SE->getSCEV(&getAssociatedValue());
9192 if (!I)
9193 return S;
9194
9195 return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
9196 }
9197
9198 /// Helper function to get a range from SCEV for the associated value at
9199 /// program point \p I.
9200 ConstantRange getConstantRangeFromSCEV(Attributor &A,
9201 const Instruction *I = nullptr) const {
9202 if (!getAnchorScope())
9203 return getWorstState(getBitWidth());
9204
9205 ScalarEvolution *SE =
9206 A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
9207 *getAnchorScope());
9208
9209 const SCEV *S = getSCEV(A, I);
9210 if (!SE || !S)
9211 return getWorstState(getBitWidth());
9212
9213 return SE->getUnsignedRange(S);
9214 }
9215
9216 /// Helper function to get a range from LVI for the associated value at
9217 /// program point \p I.
9218 ConstantRange
9219 getConstantRangeFromLVI(Attributor &A,
9220 const Instruction *CtxI = nullptr) const {
9221 if (!getAnchorScope())
9222 return getWorstState(getBitWidth());
9223
9224 LazyValueInfo *LVI =
9225 A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
9226 *getAnchorScope());
9227
9228 if (!LVI || !CtxI)
9229 return getWorstState(getBitWidth());
9230 return LVI->getConstantRange(&getAssociatedValue(),
9231 const_cast<Instruction *>(CtxI),
9232 /*UndefAllowed*/ false);
9233 }
9234
9235 /// Return true if \p CtxI is valid for querying outside analyses.
9236 /// This basically makes sure we do not ask intra-procedural analysis
9237 /// about a context in the wrong function or a context that violates
9238 /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
9239 /// if the original context of this AA is OK or should be considered invalid.
9240 bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
9241 const Instruction *CtxI,
9242 bool AllowAACtxI) const {
9243 if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
9244 return false;
9245
9246 // Our context might be in a different function, neither intra-procedural
9247 // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
9248 if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
9249 return false;
9250
9251 // If the context is not dominated by the value there are paths to the
9252 // context that do not define the value. This cannot be handled by
9253 // LazyValueInfo so we need to bail.
9254 if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
9255 InformationCache &InfoCache = A.getInfoCache();
9256 const DominatorTree *DT =
9257 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
9258 *I->getFunction());
9259 return DT && DT->dominates(I, CtxI);
9260 }
9261
9262 return true;
9263 }
9264
9265 /// See AAValueConstantRange::getAssumedConstantRange(..).
9266 ConstantRange
9267 getAssumedConstantRange(Attributor &A,
9268 const Instruction *CtxI = nullptr) const override {
9269 // TODO: Make SCEV use Attributor assumption.
9270 // We may be able to bound a variable range via assumptions in
9271 // Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
9272 // evolve to x^2 + x, then we can say that y is in [2, 12].
9273 if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
9274 /* AllowAACtxI */ false))
9275 return getAssumed();
9276
9277 ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
9278 ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
9279 return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
9280 }
9281
9282 /// Helper function to create MDNode for range metadata.
9283 static MDNode *
9284 getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
9285 const ConstantRange &AssumedConstantRange) {
9286 Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
9287 Ty, AssumedConstantRange.getLower())),
9288 ConstantAsMetadata::get(ConstantInt::get(
9289 Ty, AssumedConstantRange.getUpper()))};
9290 return MDNode::get(Ctx, LowAndHigh);
9291 }
9292
9293 /// Return true if \p Assumed is included in ranges from instruction \p I.
9294 static bool isBetterRange(const ConstantRange &Assumed,
9295 const Instruction &I) {
9296 if (Assumed.isFullSet())
9297 return false;
9298
9299 std::optional<ConstantRange> Known;
9300
9301 if (const auto *CB = dyn_cast<CallBase>(&I)) {
9302 Known = CB->getRange();
9303 } else if (MDNode *KnownRanges = I.getMetadata(LLVMContext::MD_range)) {
9304 // If multiple ranges are annotated in IR, we give up to annotate assumed
9305 // range for now.
9306
9307 // TODO: If there exists a known range which containts assumed range, we
9308 // can say assumed range is better.
9309 if (KnownRanges->getNumOperands() > 2)
9310 return false;
9311
9312 ConstantInt *Lower =
9313 mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
9314 ConstantInt *Upper =
9315 mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));
9316
9317 Known.emplace(Lower->getValue(), Upper->getValue());
9318 }
9319 return !Known || (*Known != Assumed && Known->contains(Assumed));
9320 }
9321
9322 /// Helper function to set range metadata.
9323 static bool
9324 setRangeMetadataIfisBetterRange(Instruction *I,
9325 const ConstantRange &AssumedConstantRange) {
9326 if (isBetterRange(AssumedConstantRange, *I)) {
9327 I->setMetadata(LLVMContext::MD_range,
9328 getMDNodeForConstantRange(I->getType(), I->getContext(),
9329 AssumedConstantRange));
9330 return true;
9331 }
9332 return false;
9333 }
9334 /// Helper function to set range return attribute.
9335 static bool
9336 setRangeRetAttrIfisBetterRange(Attributor &A, const IRPosition &IRP,
9337 Instruction *I,
9338 const ConstantRange &AssumedConstantRange) {
9339 if (isBetterRange(AssumedConstantRange, *I)) {
9340 A.manifestAttrs(IRP,
9341 Attribute::get(I->getContext(), Attribute::Range,
9342 AssumedConstantRange),
9343 /*ForceReplace*/ true);
9344 return true;
9345 }
9346 return false;
9347 }
9348
9349 /// See AbstractAttribute::manifest()
9350 ChangeStatus manifest(Attributor &A) override {
9351 ChangeStatus Changed = ChangeStatus::UNCHANGED;
9352 ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
9353 assert(!AssumedConstantRange.isFullSet() && "Invalid state");
9354
9355 auto &V = getAssociatedValue();
9356 if (!AssumedConstantRange.isEmptySet() &&
9357 !AssumedConstantRange.isSingleElement()) {
9358 if (Instruction *I = dyn_cast<Instruction>(&V)) {
9359 assert(I == getCtxI() && "Should not annotate an instruction which is "
9360 "not the context instruction");
9361 if (isa<LoadInst>(I))
9362 if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
9363 Changed = ChangeStatus::CHANGED;
9364 if (isa<CallInst>(I))
9365 if (setRangeRetAttrIfisBetterRange(A, getIRPosition(), I,
9366 AssumedConstantRange))
9367 Changed = ChangeStatus::CHANGED;
9368 }
9369 }
9370
9371 return Changed;
9372 }
9373};
9374
9375struct AAValueConstantRangeArgument final
9376 : AAArgumentFromCallSiteArguments<
9377 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9378 true /* BridgeCallBaseContext */> {
9379 using Base = AAArgumentFromCallSiteArguments<
9380 AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
9381 true /* BridgeCallBaseContext */>;
9382 AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
9383 : Base(IRP, A) {}
9384
9385 /// See AbstractAttribute::trackStatistics()
9386 void trackStatistics() const override {
9387 STATS_DECLTRACK_ARG_ATTR(value_range)
9388 }
9389};
9390
9391struct AAValueConstantRangeReturned
9392 : AAReturnedFromReturnedValues<AAValueConstantRange,
9393 AAValueConstantRangeImpl,
9394 AAValueConstantRangeImpl::StateType,
9395 /* PropagateCallBaseContext */ true> {
9396 using Base =
9397 AAReturnedFromReturnedValues<AAValueConstantRange,
9398 AAValueConstantRangeImpl,
9399 AAValueConstantRangeImpl::StateType,
9400 /* PropagateCallBaseContext */ true>;
9401 AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
9402 : Base(IRP, A) {}
9403
9404 /// See AbstractAttribute::initialize(...).
9405 void initialize(Attributor &A) override {
9406 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9407 indicatePessimisticFixpoint();
9408 }
9409
9410 /// See AbstractAttribute::trackStatistics()
9411 void trackStatistics() const override {
9412 STATS_DECLTRACK_FNRET_ATTR(value_range)
9413 }
9414};
9415
9416struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
9417 AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
9418 : AAValueConstantRangeImpl(IRP, A) {}
9419
9420 /// See AbstractAttribute::initialize(...).
9421 void initialize(Attributor &A) override {
9422 AAValueConstantRangeImpl::initialize(A);
9423 if (isAtFixpoint())
9424 return;
9425
9426 Value &V = getAssociatedValue();
9427
9428 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9429 unionAssumed(ConstantRange(C->getValue()));
9430 indicateOptimisticFixpoint();
9431 return;
9432 }
9433
9434 if (isa<UndefValue>(&V)) {
9435 // Collapse the undef state to 0.
9436 unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
9437 indicateOptimisticFixpoint();
9438 return;
9439 }
9440
9441 if (isa<CallBase>(&V))
9442 return;
9443
9444 if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
9445 return;
9446
9447 // If it is a load instruction with range metadata, use it.
9448 if (LoadInst *LI = dyn_cast<LoadInst>(&V))
9449 if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
9450 intersectKnown(getConstantRangeFromMetadata(*RangeMD));
9451 return;
9452 }
9453
9454 // We can work with PHI and select instruction as we traverse their operands
9455 // during update.
9456 if (isa<SelectInst>(V) || isa<PHINode>(V))
9457 return;
9458
9459 // Otherwise we give up.
9460 indicatePessimisticFixpoint();
9461
9462 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
9463 << getAssociatedValue() << "\n");
9464 }
9465
9466 bool calculateBinaryOperator(
9467 Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
9468 const Instruction *CtxI,
9469 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9470 Value *LHS = BinOp->getOperand(0);
9471 Value *RHS = BinOp->getOperand(1);
9472
9473 // Simplify the operands first.
9474 bool UsedAssumedInformation = false;
9475 const auto &SimplifiedLHS = A.getAssumedSimplified(
9476 IRPosition::value(*LHS, getCallBaseContext()), *this,
9477 UsedAssumedInformation, AA::Interprocedural);
9478 if (!SimplifiedLHS.has_value())
9479 return true;
9480 if (!*SimplifiedLHS)
9481 return false;
9482 LHS = *SimplifiedLHS;
9483
9484 const auto &SimplifiedRHS = A.getAssumedSimplified(
9485 IRPosition::value(*RHS, getCallBaseContext()), *this,
9486 UsedAssumedInformation, AA::Interprocedural);
9487 if (!SimplifiedRHS.has_value())
9488 return true;
9489 if (!*SimplifiedRHS)
9490 return false;
9491 RHS = *SimplifiedRHS;
9492
9493 // TODO: Allow non integers as well.
9494 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9495 return false;
9496
9497 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9498 *this, IRPosition::value(*LHS, getCallBaseContext()),
9499 DepClassTy::REQUIRED);
9500 if (!LHSAA)
9501 return false;
9502 QuerriedAAs.push_back(LHSAA);
9503 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9504
9505 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9506 *this, IRPosition::value(*RHS, getCallBaseContext()),
9507 DepClassTy::REQUIRED);
9508 if (!RHSAA)
9509 return false;
9510 QuerriedAAs.push_back(RHSAA);
9511 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9512
9513 auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);
9514
9515 T.unionAssumed(AssumedRange);
9516
9517 // TODO: Track a known state too.
9518
9519 return T.isValidState();
9520 }
9521
9522 bool calculateCastInst(
9523 Attributor &A, CastInst *CastI, IntegerRangeState &T,
9524 const Instruction *CtxI,
9525 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9526 assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
9527 // TODO: Allow non integers as well.
9528 Value *OpV = CastI->getOperand(0);
9529
9530 // Simplify the operand first.
9531 bool UsedAssumedInformation = false;
9532 const auto &SimplifiedOpV = A.getAssumedSimplified(
9533 IRPosition::value(*OpV, getCallBaseContext()), *this,
9534 UsedAssumedInformation, AA::Interprocedural);
9535 if (!SimplifiedOpV.has_value())
9536 return true;
9537 if (!*SimplifiedOpV)
9538 return false;
9539 OpV = *SimplifiedOpV;
9540
9541 if (!OpV->getType()->isIntegerTy())
9542 return false;
9543
9544 auto *OpAA = A.getAAFor<AAValueConstantRange>(
9545 *this, IRPosition::value(*OpV, getCallBaseContext()),
9546 DepClassTy::REQUIRED);
9547 if (!OpAA)
9548 return false;
9549 QuerriedAAs.push_back(OpAA);
9550 T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
9551 getState().getBitWidth()));
9552 return T.isValidState();
9553 }
9554
9555 bool
9556 calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
9557 const Instruction *CtxI,
9558 SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
9559 Value *LHS = CmpI->getOperand(0);
9560 Value *RHS = CmpI->getOperand(1);
9561
9562 // Simplify the operands first.
9563 bool UsedAssumedInformation = false;
9564 const auto &SimplifiedLHS = A.getAssumedSimplified(
9565 IRPosition::value(*LHS, getCallBaseContext()), *this,
9566 UsedAssumedInformation, AA::Interprocedural);
9567 if (!SimplifiedLHS.has_value())
9568 return true;
9569 if (!*SimplifiedLHS)
9570 return false;
9571 LHS = *SimplifiedLHS;
9572
9573 const auto &SimplifiedRHS = A.getAssumedSimplified(
9574 IRPosition::value(*RHS, getCallBaseContext()), *this,
9575 UsedAssumedInformation, AA::Interprocedural);
9576 if (!SimplifiedRHS.has_value())
9577 return true;
9578 if (!*SimplifiedRHS)
9579 return false;
9580 RHS = *SimplifiedRHS;
9581
9582 // TODO: Allow non integers as well.
9583 if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
9584 return false;
9585
9586 auto *LHSAA = A.getAAFor<AAValueConstantRange>(
9587 *this, IRPosition::value(*LHS, getCallBaseContext()),
9588 DepClassTy::REQUIRED);
9589 if (!LHSAA)
9590 return false;
9591 QuerriedAAs.push_back(LHSAA);
9592 auto *RHSAA = A.getAAFor<AAValueConstantRange>(
9593 *this, IRPosition::value(*RHS, getCallBaseContext()),
9594 DepClassTy::REQUIRED);
9595 if (!RHSAA)
9596 return false;
9597 QuerriedAAs.push_back(RHSAA);
9598 auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
9599 auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);
9600
9601 // If one of them is empty set, we can't decide.
9602 if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
9603 return true;
9604
9605 bool MustTrue = false, MustFalse = false;
9606
9607 auto AllowedRegion =
9609
9610 if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
9611 MustFalse = true;
9612
9613 if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
9614 MustTrue = true;
9615
9616 assert((!MustTrue || !MustFalse) &&
9617 "Either MustTrue or MustFalse should be false!");
9618
9619 if (MustTrue)
9620 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
9621 else if (MustFalse)
9622 T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
9623 else
9624 T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));
9625
9626 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
9627 << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
9628 << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
9629 << *RHSAA);
9630
9631 // TODO: Track a known state too.
9632 return T.isValidState();
9633 }
9634
9635 /// See AbstractAttribute::updateImpl(...).
9636 ChangeStatus updateImpl(Attributor &A) override {
9637
9638 IntegerRangeState T(getBitWidth());
9639 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
9641 if (!I || isa<CallBase>(I)) {
9642
9643 // Simplify the operand first.
9644 bool UsedAssumedInformation = false;
9645 const auto &SimplifiedOpV = A.getAssumedSimplified(
9646 IRPosition::value(V, getCallBaseContext()), *this,
9647 UsedAssumedInformation, AA::Interprocedural);
9648 if (!SimplifiedOpV.has_value())
9649 return true;
9650 if (!*SimplifiedOpV)
9651 return false;
9652 Value *VPtr = *SimplifiedOpV;
9653
9654 // If the value is not instruction, we query AA to Attributor.
9655 const auto *AA = A.getAAFor<AAValueConstantRange>(
9656 *this, IRPosition::value(*VPtr, getCallBaseContext()),
9657 DepClassTy::REQUIRED);
9658
9659 // Clamp operator is not used to utilize a program point CtxI.
9660 if (AA)
9661 T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
9662 else
9663 return false;
9664
9665 return T.isValidState();
9666 }
9667
9669 if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
9670 if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
9671 return false;
9672 } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
9673 if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
9674 return false;
9675 } else if (auto *CastI = dyn_cast<CastInst>(I)) {
9676 if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
9677 return false;
9678 } else {
9679 // Give up with other instructions.
9680 // TODO: Add other instructions
9681
9682 T.indicatePessimisticFixpoint();
9683 return false;
9684 }
9685
9686 // Catch circular reasoning in a pessimistic way for now.
9687 // TODO: Check how the range evolves and if we stripped anything, see also
9688 // AADereferenceable or AAAlign for similar situations.
9689 for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
9690 if (QueriedAA != this)
9691 continue;
9692 // If we are in a stady state we do not need to worry.
9693 if (T.getAssumed() == getState().getAssumed())
9694 continue;
9695 T.indicatePessimisticFixpoint();
9696 }
9697
9698 return T.isValidState();
9699 };
9700
9701 if (!VisitValueCB(getAssociatedValue(), getCtxI()))
9702 return indicatePessimisticFixpoint();
9703
9704 // Ensure that long def-use chains can't cause circular reasoning either by
9705 // introducing a cutoff below.
9706 if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
9707 return ChangeStatus::UNCHANGED;
9708 if (++NumChanges > MaxNumChanges) {
9709 LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
9710 << " but only " << MaxNumChanges
9711 << " are allowed to avoid cyclic reasoning.");
9712 return indicatePessimisticFixpoint();
9713 }
9714 return ChangeStatus::CHANGED;
9715 }
9716
9717 /// See AbstractAttribute::trackStatistics()
9718 void trackStatistics() const override {
9720 }
9721
9722 /// Tracker to bail after too many widening steps of the constant range.
9723 int NumChanges = 0;
9724
9725 /// Upper bound for the number of allowed changes (=widening steps) for the
9726 /// constant range before we give up.
9727 static constexpr int MaxNumChanges = 5;
9728};
9729
9730struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
9731 AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
9732 : AAValueConstantRangeImpl(IRP, A) {}
9733
9734 /// See AbstractAttribute::initialize(...).
9735 ChangeStatus updateImpl(Attributor &A) override {
9736 llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
9737 "not be called");
9738 }
9739
9740 /// See AbstractAttribute::trackStatistics()
9741 void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
9742};
9743
9744struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
9745 AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
9746 : AAValueConstantRangeFunction(IRP, A) {}
9747
9748 /// See AbstractAttribute::trackStatistics()
9749 void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
9750};
9751
9752struct AAValueConstantRangeCallSiteReturned
9753 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9754 AAValueConstantRangeImpl::StateType,
9755 /* IntroduceCallBaseContext */ true> {
9756 AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
9757 : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
9758 AAValueConstantRangeImpl::StateType,
9759 /* IntroduceCallBaseContext */ true>(IRP, A) {}
9760
9761 /// See AbstractAttribute::initialize(...).
9762 void initialize(Attributor &A) override {
9763 // If it is a call instruction with range attribute, use the range.
9764 if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue())) {
9765 if (std::optional<ConstantRange> Range = CI->getRange())
9766 intersectKnown(*Range);
9767 }
9768
9769 AAValueConstantRangeImpl::initialize(A);
9770 }
9771
9772 /// See AbstractAttribute::trackStatistics()
9773 void trackStatistics() const override {
9774 STATS_DECLTRACK_CSRET_ATTR(value_range)
9775 }
9776};
9777struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
9778 AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
9779 : AAValueConstantRangeFloating(IRP, A) {}
9780
9781 /// See AbstractAttribute::manifest()
9782 ChangeStatus manifest(Attributor &A) override {
9783 return ChangeStatus::UNCHANGED;
9784 }
9785
9786 /// See AbstractAttribute::trackStatistics()
9787 void trackStatistics() const override {
9788 STATS_DECLTRACK_CSARG_ATTR(value_range)
9789 }
9790};
9791} // namespace
9792
9793/// ------------------ Potential Values Attribute -------------------------
9794
9795namespace {
9796struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
9797 using StateType = PotentialConstantIntValuesState;
9798
9799 AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
9800 : AAPotentialConstantValues(IRP, A) {}
9801
9802 /// See AbstractAttribute::initialize(..).
9803 void initialize(Attributor &A) override {
9804 if (A.hasSimplificationCallback(getIRPosition()))
9805 indicatePessimisticFixpoint();
9806 else
9807 AAPotentialConstantValues::initialize(A);
9808 }
9809
9810 bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
9811 bool &ContainsUndef, bool ForSelf) {
9813 bool UsedAssumedInformation = false;
9814 if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
9815 UsedAssumedInformation)) {
9816 // Avoid recursion when the caller is computing constant values for this
9817 // IRP itself.
9818 if (ForSelf)
9819 return false;
9820 if (!IRP.getAssociatedType()->isIntegerTy())
9821 return false;
9822 auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
9823 *this, IRP, DepClassTy::REQUIRED);
9824 if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
9825 return false;
9826 ContainsUndef = PotentialValuesAA->getState().undefIsContained();
9827 S = PotentialValuesAA->getState().getAssumedSet();
9828 return true;
9829 }
9830
9831 // Copy all the constant values, except UndefValue. ContainsUndef is true
9832 // iff Values contains only UndefValue instances. If there are other known
9833 // constants, then UndefValue is dropped.
9834 ContainsUndef = false;
9835 for (auto &It : Values) {
9836 if (isa<UndefValue>(It.getValue())) {
9837 ContainsUndef = true;
9838 continue;
9839 }
9840 auto *CI = dyn_cast<ConstantInt>(It.getValue());
9841 if (!CI)
9842 return false;
9843 S.insert(CI->getValue());
9844 }
9845 ContainsUndef &= S.empty();
9846
9847 return true;
9848 }
9849
9850 /// See AbstractAttribute::getAsStr().
9851 const std::string getAsStr(Attributor *A) const override {
9852 std::string Str;
9853 llvm::raw_string_ostream OS(Str);
9854 OS << getState();
9855 return Str;
9856 }
9857
9858 /// See AbstractAttribute::updateImpl(...).
9859 ChangeStatus updateImpl(Attributor &A) override {
9860 return indicatePessimisticFixpoint();
9861 }
9862};
9863
9864struct AAPotentialConstantValuesArgument final
9865 : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9866 AAPotentialConstantValuesImpl,
9867 PotentialConstantIntValuesState> {
9868 using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
9869 AAPotentialConstantValuesImpl,
9871 AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
9872 : Base(IRP, A) {}
9873
9874 /// See AbstractAttribute::trackStatistics()
9875 void trackStatistics() const override {
9876 STATS_DECLTRACK_ARG_ATTR(potential_values)
9877 }
9878};
9879
9880struct AAPotentialConstantValuesReturned
9881 : AAReturnedFromReturnedValues<AAPotentialConstantValues,
9882 AAPotentialConstantValuesImpl> {
9883 using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
9884 AAPotentialConstantValuesImpl>;
9885 AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
9886 : Base(IRP, A) {}
9887
9888 void initialize(Attributor &A) override {
9889 if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
9890 indicatePessimisticFixpoint();
9891 Base::initialize(A);
9892 }
9893
9894 /// See AbstractAttribute::trackStatistics()
9895 void trackStatistics() const override {
9896 STATS_DECLTRACK_FNRET_ATTR(potential_values)
9897 }
9898};
9899
9900struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
9901 AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
9902 : AAPotentialConstantValuesImpl(IRP, A) {}
9903
9904 /// See AbstractAttribute::initialize(..).
9905 void initialize(Attributor &A) override {
9906 AAPotentialConstantValuesImpl::initialize(A);
9907 if (isAtFixpoint())
9908 return;
9909
9910 Value &V = getAssociatedValue();
9911
9912 if (auto *C = dyn_cast<ConstantInt>(&V)) {
9913 unionAssumed(C->getValue());
9914 indicateOptimisticFixpoint();
9915 return;
9916 }
9917
9918 if (isa<UndefValue>(&V)) {
9919 unionAssumedWithUndef();
9920 indicateOptimisticFixpoint();
9921 return;
9922 }
9923
9924 if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
9925 return;
9926
9927 if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
9928 return;
9929
9930 indicatePessimisticFixpoint();
9931
9932 LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
9933 << getAssociatedValue() << "\n");
9934 }
9935
9936 static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
9937 const APInt &RHS) {
9938 return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
9939 }
9940
9941 static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
9942 uint32_t ResultBitWidth) {
9943 Instruction::CastOps CastOp = CI->getOpcode();
9944 switch (CastOp) {
9945 default:
9946 llvm_unreachable("unsupported or not integer cast");
9947 case Instruction::Trunc:
9948 return Src.trunc(ResultBitWidth);
9949 case Instruction::SExt:
9950 return Src.sext(ResultBitWidth);
9951 case Instruction::ZExt:
9952 return Src.zext(ResultBitWidth);
9953 case Instruction::BitCast:
9954 return Src;
9955 }
9956 }
9957
9958 static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
9959 const APInt &LHS, const APInt &RHS,
9960 bool &SkipOperation, bool &Unsupported) {
9961 Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
9962 // Unsupported is set to true when the binary operator is not supported.
9963 // SkipOperation is set to true when UB occur with the given operand pair
9964 // (LHS, RHS).
9965 // TODO: we should look at nsw and nuw keywords to handle operations
9966 // that create poison or undef value.
9967 switch (BinOpcode) {
9968 default:
9969 Unsupported = true;
9970 return LHS;
9971 case Instruction::Add:
9972 return LHS + RHS;
9973 case Instruction::Sub:
9974 return LHS - RHS;
9975 case Instruction::Mul:
9976 return LHS * RHS;
9977 case Instruction::UDiv:
9978 if (RHS.isZero()) {
9979 SkipOperation = true;
9980 return LHS;
9981 }
9982 return LHS.udiv(RHS);
9983 case Instruction::SDiv:
9984 if (RHS.isZero()) {
9985 SkipOperation = true;
9986 return LHS;
9987 }
9988 return LHS.sdiv(RHS);
9989 case Instruction::URem:
9990 if (RHS.isZero()) {
9991 SkipOperation = true;
9992 return LHS;
9993 }
9994 return LHS.urem(RHS);
9995 case Instruction::SRem:
9996 if (RHS.isZero()) {
9997 SkipOperation = true;
9998 return LHS;
9999 }
10000 return LHS.srem(RHS);
10001 case Instruction::Shl:
10002 return LHS.shl(RHS);
10003 case Instruction::LShr:
10004 return LHS.lshr(RHS);
10005 case Instruction::AShr:
10006 return LHS.ashr(RHS);
10007 case Instruction::And:
10008 return LHS & RHS;
10009 case Instruction::Or:
10010 return LHS | RHS;
10011 case Instruction::Xor:
10012 return LHS ^ RHS;
10013 }
10014 }
10015
10016 bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
10017 const APInt &LHS, const APInt &RHS) {
10018 bool SkipOperation = false;
10019 bool Unsupported = false;
10020 APInt Result =
10021 calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
10022 if (Unsupported)
10023 return false;
10024 // If SkipOperation is true, we can ignore this operand pair (L, R).
10025 if (!SkipOperation)
10026 unionAssumed(Result);
10027 return isValidState();
10028 }
10029
10030 ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
10031 auto AssumedBefore = getAssumed();
10032 Value *LHS = ICI->getOperand(0);
10033 Value *RHS = ICI->getOperand(1);
10034
10035 bool LHSContainsUndef = false, RHSContainsUndef = false;
10036 SetTy LHSAAPVS, RHSAAPVS;
10037 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
10038 LHSContainsUndef, /* ForSelf */ false) ||
10039 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10040 RHSContainsUndef, /* ForSelf */ false))
10041 return indicatePessimisticFixpoint();
10042
10043 // TODO: make use of undef flag to limit potential values aggressively.
10044 bool MaybeTrue = false, MaybeFalse = false;
10045 const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
10046 if (LHSContainsUndef && RHSContainsUndef) {
10047 // The result of any comparison between undefs can be soundly replaced
10048 // with undef.
10049 unionAssumedWithUndef();
10050 } else if (LHSContainsUndef) {
10051 for (const APInt &R : RHSAAPVS) {
10052 bool CmpResult = calculateICmpInst(ICI, Zero, R);
10053 MaybeTrue |= CmpResult;
10054 MaybeFalse |= !CmpResult;
10055 if (MaybeTrue & MaybeFalse)
10056 return indicatePessimisticFixpoint();
10057 }
10058 } else if (RHSContainsUndef) {
10059 for (const APInt &L : LHSAAPVS) {
10060 bool CmpResult = calculateICmpInst(ICI, L, Zero);
10061 MaybeTrue |= CmpResult;
10062 MaybeFalse |= !CmpResult;
10063 if (MaybeTrue & MaybeFalse)
10064 return indicatePessimisticFixpoint();
10065 }
10066 } else {
10067 for (const APInt &L : LHSAAPVS) {
10068 for (const APInt &R : RHSAAPVS) {
10069 bool CmpResult = calculateICmpInst(ICI, L, R);
10070 MaybeTrue |= CmpResult;
10071 MaybeFalse |= !CmpResult;
10072 if (MaybeTrue & MaybeFalse)
10073 return indicatePessimisticFixpoint();
10074 }
10075 }
10076 }
10077 if (MaybeTrue)
10078 unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
10079 if (MaybeFalse)
10080 unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
10081 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10082 : ChangeStatus::CHANGED;
10083 }
10084
10085 ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
10086 auto AssumedBefore = getAssumed();
10087 Value *LHS = SI->getTrueValue();
10088 Value *RHS = SI->getFalseValue();
10089
10090 bool UsedAssumedInformation = false;
10091 std::optional<Constant *> C = A.getAssumedConstant(
10092 *SI->getCondition(), *this, UsedAssumedInformation);
10093
10094 // Check if we only need one operand.
10095 bool OnlyLeft = false, OnlyRight = false;
10096 if (C && *C && (*C)->isOneValue())
10097 OnlyLeft = true;
10098 else if (C && *C && (*C)->isNullValue())
10099 OnlyRight = true;
10100
10101 bool LHSContainsUndef = false, RHSContainsUndef = false;
10102 SetTy LHSAAPVS, RHSAAPVS;
10103 if (!OnlyRight &&
10104 !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
10105 LHSContainsUndef, /* ForSelf */ false))
10106 return indicatePessimisticFixpoint();
10107
10108 if (!OnlyLeft &&
10109 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10110 RHSContainsUndef, /* ForSelf */ false))
10111 return indicatePessimisticFixpoint();
10112
10113 if (OnlyLeft || OnlyRight) {
10114 // select (true/false), lhs, rhs
10115 auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
10116 auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;
10117
10118 if (Undef)
10119 unionAssumedWithUndef();
10120 else {
10121 for (const auto &It : *OpAA)
10122 unionAssumed(It);
10123 }
10124
10125 } else if (LHSContainsUndef && RHSContainsUndef) {
10126 // select i1 *, undef , undef => undef
10127 unionAssumedWithUndef();
10128 } else {
10129 for (const auto &It : LHSAAPVS)
10130 unionAssumed(It);
10131 for (const auto &It : RHSAAPVS)
10132 unionAssumed(It);
10133 }
10134 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10135 : ChangeStatus::CHANGED;
10136 }
10137
10138 ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
10139 auto AssumedBefore = getAssumed();
10140 if (!CI->isIntegerCast())
10141 return indicatePessimisticFixpoint();
10142 assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
10143 uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
10144 Value *Src = CI->getOperand(0);
10145
10146 bool SrcContainsUndef = false;
10147 SetTy SrcPVS;
10148 if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
10149 SrcContainsUndef, /* ForSelf */ false))
10150 return indicatePessimisticFixpoint();
10151
10152 if (SrcContainsUndef)
10153 unionAssumedWithUndef();
10154 else {
10155 for (const APInt &S : SrcPVS) {
10156 APInt T = calculateCastInst(CI, S, ResultBitWidth);
10157 unionAssumed(T);
10158 }
10159 }
10160 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10161 : ChangeStatus::CHANGED;
10162 }
10163
10164 ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
10165 auto AssumedBefore = getAssumed();
10166 Value *LHS = BinOp->getOperand(0);
10167 Value *RHS = BinOp->getOperand(1);
10168
10169 bool LHSContainsUndef = false, RHSContainsUndef = false;
10170 SetTy LHSAAPVS, RHSAAPVS;
10171 if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
10172 LHSContainsUndef, /* ForSelf */ false) ||
10173 !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
10174 RHSContainsUndef, /* ForSelf */ false))
10175 return indicatePessimisticFixpoint();
10176
10177 const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);
10178
10179 // TODO: make use of undef flag to limit potential values aggressively.
10180 if (LHSContainsUndef && RHSContainsUndef) {
10181 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
10182 return indicatePessimisticFixpoint();
10183 } else if (LHSContainsUndef) {
10184 for (const APInt &R : RHSAAPVS) {
10185 if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
10186 return indicatePessimisticFixpoint();
10187 }
10188 } else if (RHSContainsUndef) {
10189 for (const APInt &L : LHSAAPVS) {
10190 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
10191 return indicatePessimisticFixpoint();
10192 }
10193 } else {
10194 for (const APInt &L : LHSAAPVS) {
10195 for (const APInt &R : RHSAAPVS) {
10196 if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
10197 return indicatePessimisticFixpoint();
10198 }
10199 }
10200 }
10201 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10202 : ChangeStatus::CHANGED;
10203 }
10204
10205 ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
10206 auto AssumedBefore = getAssumed();
10207 SetTy Incoming;
10208 bool ContainsUndef;
10209 if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
10210 ContainsUndef, /* ForSelf */ true))
10211 return indicatePessimisticFixpoint();
10212 if (ContainsUndef) {
10213 unionAssumedWithUndef();
10214 } else {
10215 for (const auto &It : Incoming)
10216 unionAssumed(It);
10217 }
10218 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10219 : ChangeStatus::CHANGED;
10220 }
10221
10222 /// See AbstractAttribute::updateImpl(...).
10223 ChangeStatus updateImpl(Attributor &A) override {
10224 Value &V = getAssociatedValue();
10226
10227 if (auto *ICI = dyn_cast<ICmpInst>(I))
10228 return updateWithICmpInst(A, ICI);
10229
10230 if (auto *SI = dyn_cast<SelectInst>(I))
10231 return updateWithSelectInst(A, SI);
10232
10233 if (auto *CI = dyn_cast<CastInst>(I))
10234 return updateWithCastInst(A, CI);
10235
10236 if (auto *BinOp = dyn_cast<BinaryOperator>(I))
10237 return updateWithBinaryOperator(A, BinOp);
10238
10239 if (isa<PHINode>(I) || isa<LoadInst>(I))
10240 return updateWithInstruction(A, I);
10241
10242 return indicatePessimisticFixpoint();
10243 }
10244
10245 /// See AbstractAttribute::trackStatistics()
10246 void trackStatistics() const override {
10247 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
10248 }
10249};
10250
10251struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
10252 AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
10253 : AAPotentialConstantValuesImpl(IRP, A) {}
10254
10255 /// See AbstractAttribute::initialize(...).
10256 ChangeStatus updateImpl(Attributor &A) override {
10258 "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
10259 "not be called");
10260 }
10261
10262 /// See AbstractAttribute::trackStatistics()
10263 void trackStatistics() const override {
10264 STATS_DECLTRACK_FN_ATTR(potential_values)
10265 }
10266};
10267
10268struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
10269 AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
10270 : AAPotentialConstantValuesFunction(IRP, A) {}
10271
10272 /// See AbstractAttribute::trackStatistics()
10273 void trackStatistics() const override {
10274 STATS_DECLTRACK_CS_ATTR(potential_values)
10275 }
10276};
10277
10278struct AAPotentialConstantValuesCallSiteReturned
10279 : AACalleeToCallSite<AAPotentialConstantValues,
10280 AAPotentialConstantValuesImpl> {
10281 AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
10282 Attributor &A)
10283 : AACalleeToCallSite<AAPotentialConstantValues,
10284 AAPotentialConstantValuesImpl>(IRP, A) {}
10285
10286 /// See AbstractAttribute::trackStatistics()
10287 void trackStatistics() const override {
10288 STATS_DECLTRACK_CSRET_ATTR(potential_values)
10289 }
10290};
10291
10292struct AAPotentialConstantValuesCallSiteArgument
10293 : AAPotentialConstantValuesFloating {
10294 AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
10295 Attributor &A)
10296 : AAPotentialConstantValuesFloating(IRP, A) {}
10297
10298 /// See AbstractAttribute::initialize(..).
10299 void initialize(Attributor &A) override {
10300 AAPotentialConstantValuesImpl::initialize(A);
10301 if (isAtFixpoint())
10302 return;
10303
10304 Value &V = getAssociatedValue();
10305
10306 if (auto *C = dyn_cast<ConstantInt>(&V)) {
10307 unionAssumed(C->getValue());
10308 indicateOptimisticFixpoint();
10309 return;
10310 }
10311
10312 if (isa<UndefValue>(&V)) {
10313 unionAssumedWithUndef();
10314 indicateOptimisticFixpoint();
10315 return;
10316 }
10317 }
10318
10319 /// See AbstractAttribute::updateImpl(...).
10320 ChangeStatus updateImpl(Attributor &A) override {
10321 Value &V = getAssociatedValue();
10322 auto AssumedBefore = getAssumed();
10323 auto *AA = A.getAAFor<AAPotentialConstantValues>(
10324 *this, IRPosition::value(V), DepClassTy::REQUIRED);
10325 if (!AA)
10326 return indicatePessimisticFixpoint();
10327 const auto &S = AA->getAssumed();
10328 unionAssumed(S);
10329 return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
10330 : ChangeStatus::CHANGED;
10331 }
10332
10333 /// See AbstractAttribute::trackStatistics()
10334 void trackStatistics() const override {
10335 STATS_DECLTRACK_CSARG_ATTR(potential_values)
10336 }
10337};
10338} // namespace
10339
10340/// ------------------------ NoUndef Attribute ---------------------------------
10342 Attribute::AttrKind ImpliedAttributeKind,
10343 bool IgnoreSubsumingPositions) {
10344 assert(ImpliedAttributeKind == Attribute::NoUndef &&
10345 "Unexpected attribute kind");
10346 if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
10347 Attribute::NoUndef))
10348 return true;
10349
10350 Value &Val = IRP.getAssociatedValue();
10353 LLVMContext &Ctx = Val.getContext();
10354 A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
10355 return true;
10356 }
10357
10358 return false;
10359}
10360
10361namespace {
10362struct AANoUndefImpl : AANoUndef {
10363 AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}
10364
10365 /// See AbstractAttribute::initialize(...).
10366 void initialize(Attributor &A) override {
10367 Value &V = getAssociatedValue();
10368 if (isa<UndefValue>(V))
10369 indicatePessimisticFixpoint();
10370 assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
10371 }
10372
10373 /// See followUsesInMBEC
10374 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10375 AANoUndef::StateType &State) {
10376 const Value *UseV = U->get();
10377 const DominatorTree *DT = nullptr;
10378 AssumptionCache *AC = nullptr;
10379 InformationCache &InfoCache = A.getInfoCache();
10380 if (Function *F = getAnchorScope()) {
10381 DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10382 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10383 }
10384 State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
10385 bool TrackUse = false;
10386 // Track use for instructions which must produce undef or poison bits when
10387 // at least one operand contains such bits.
10389 TrackUse = true;
10390 return TrackUse;
10391 }
10392
10393 /// See AbstractAttribute::getAsStr().
10394 const std::string getAsStr(Attributor *A) const override {
10395 return getAssumed() ? "noundef" : "may-undef-or-poison";
10396 }
10397
10398 ChangeStatus manifest(Attributor &A) override {
10399 // We don't manifest noundef attribute for dead positions because the
10400 // associated values with dead positions would be replaced with undef
10401 // values.
10402 bool UsedAssumedInformation = false;
10403 if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
10404 UsedAssumedInformation))
10405 return ChangeStatus::UNCHANGED;
10406 // A position whose simplified value does not have any value is
10407 // considered to be dead. We don't manifest noundef in such positions for
10408 // the same reason above.
10409 if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
10411 .has_value())
10412 return ChangeStatus::UNCHANGED;
10413 return AANoUndef::manifest(A);
10414 }
10415};
10416
10417struct AANoUndefFloating : public AANoUndefImpl {
10418 AANoUndefFloating(const IRPosition &IRP, Attributor &A)
10419 : AANoUndefImpl(IRP, A) {}
10420
10421 /// See AbstractAttribute::initialize(...).
10422 void initialize(Attributor &A) override {
10423 AANoUndefImpl::initialize(A);
10424 if (!getState().isAtFixpoint() && getAnchorScope() &&
10425 !getAnchorScope()->isDeclaration())
10426 if (Instruction *CtxI = getCtxI())
10427 followUsesInMBEC(*this, A, getState(), *CtxI);
10428 }
10429
10430 /// See AbstractAttribute::updateImpl(...).
10431 ChangeStatus updateImpl(Attributor &A) override {
10432 auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
10433 bool IsKnownNoUndef;
10435 A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
10436 };
10437
10438 bool Stripped;
10439 bool UsedAssumedInformation = false;
10440 Value *AssociatedValue = &getAssociatedValue();
10442 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10443 AA::AnyScope, UsedAssumedInformation))
10444 Stripped = false;
10445 else
10446 Stripped =
10447 Values.size() != 1 || Values.front().getValue() != AssociatedValue;
10448
10449 if (!Stripped) {
10450 // If we haven't stripped anything we might still be able to use a
10451 // different AA, but only if the IRP changes. Effectively when we
10452 // interpret this not as a call site value but as a floating/argument
10453 // value.
10454 const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
10455 if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
10456 return indicatePessimisticFixpoint();
10457 return ChangeStatus::UNCHANGED;
10458 }
10459
10460 for (const auto &VAC : Values)
10461 if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
10462 return indicatePessimisticFixpoint();
10463
10464 return ChangeStatus::UNCHANGED;
10465 }
10466
10467 /// See AbstractAttribute::trackStatistics()
10468 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10469};
10470
10471struct AANoUndefReturned final
10472 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {
10473 AANoUndefReturned(const IRPosition &IRP, Attributor &A)
10474 : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl>(IRP, A) {}
10475
10476 /// See AbstractAttribute::trackStatistics()
10477 void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
10478};
10479
10480struct AANoUndefArgument final
10481 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {
10482 AANoUndefArgument(const IRPosition &IRP, Attributor &A)
10483 : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl>(IRP, A) {}
10484
10485 /// See AbstractAttribute::trackStatistics()
10486 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
10487};
10488
10489struct AANoUndefCallSiteArgument final : AANoUndefFloating {
10490 AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
10491 : AANoUndefFloating(IRP, A) {}
10492
10493 /// See AbstractAttribute::trackStatistics()
10494 void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
10495};
10496
10497struct AANoUndefCallSiteReturned final
10498 : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {
10499 AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
10500 : AACalleeToCallSite<AANoUndef, AANoUndefImpl>(IRP, A) {}
10501
10502 /// See AbstractAttribute::trackStatistics()
10503 void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
10504};
10505
10506/// ------------------------ NoFPClass Attribute -------------------------------
10507
10508struct AANoFPClassImpl : AANoFPClass {
10509 AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}
10510
10511 void initialize(Attributor &A) override {
10512 const IRPosition &IRP = getIRPosition();
10513
10514 Value &V = IRP.getAssociatedValue();
10515 if (isa<UndefValue>(V)) {
10516 indicateOptimisticFixpoint();
10517 return;
10518 }
10519
10521 A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
10522 for (const auto &Attr : Attrs) {
10523 addKnownBits(Attr.getNoFPClass());
10524 }
10525
10526 Instruction *CtxI = getCtxI();
10527
10528 if (getPositionKind() != IRPosition::IRP_RETURNED) {
10529 const DataLayout &DL = A.getDataLayout();
10530 InformationCache &InfoCache = A.getInfoCache();
10531
10532 const DominatorTree *DT = nullptr;
10533 AssumptionCache *AC = nullptr;
10534 const TargetLibraryInfo *TLI = nullptr;
10535 Function *F = getAnchorScope();
10536 if (F) {
10537 TLI = InfoCache.getTargetLibraryInfoForFunction(*F);
10538 if (!F->isDeclaration()) {
10539 DT =
10540 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
10541 AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
10542 }
10543 }
10544
10545 SimplifyQuery Q(DL, TLI, DT, AC, CtxI);
10546
10547 KnownFPClass KnownFPClass = computeKnownFPClass(&V, fcAllFlags, Q);
10548 addKnownBits(~KnownFPClass.getKnownFPClasses());
10549 }
10550
10551 if (CtxI)
10552 followUsesInMBEC(*this, A, getState(), *CtxI);
10553 }
10554
10555 /// See followUsesInMBEC
10556 bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
10557 AANoFPClass::StateType &State) {
10558 // TODO: Determine what instructions can be looked through.
10559 auto *CB = dyn_cast<CallBase>(I);
10560 if (!CB)
10561 return false;
10562
10563 if (!CB->isArgOperand(U))
10564 return false;
10565
10566 unsigned ArgNo = CB->getArgOperandNo(U);
10567 IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
10568 if (auto *NoFPAA = A.getAAFor<AANoFPClass>(*this, IRP, DepClassTy::NONE))
10569 State.addKnownBits(NoFPAA->getState().getKnown());
10570 return false;
10571 }
10572
10573 const std::string getAsStr(Attributor *A) const override {
10574 std::string Result = "nofpclass";
10575 raw_string_ostream OS(Result);
10576 OS << getKnownNoFPClass() << '/' << getAssumedNoFPClass();
10577 return Result;
10578 }
10579
10580 void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
10581 SmallVectorImpl<Attribute> &Attrs) const override {
10582 Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
10583 }
10584};
10585
10586struct AANoFPClassFloating : public AANoFPClassImpl {
10587 AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
10588 : AANoFPClassImpl(IRP, A) {}
10589
10590 /// See AbstractAttribute::updateImpl(...).
10591 ChangeStatus updateImpl(Attributor &A) override {
10593 bool UsedAssumedInformation = false;
10594 if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
10595 AA::AnyScope, UsedAssumedInformation)) {
10596 Values.push_back({getAssociatedValue(), getCtxI()});
10597 }
10598
10599 StateType T;
10600 auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
10601 const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
10602 DepClassTy::REQUIRED);
10603 if (!AA || this == AA) {
10604 T.indicatePessimisticFixpoint();
10605 } else {
10606 const AANoFPClass::StateType &S =
10607 static_cast<const AANoFPClass::StateType &>(AA->getState());
10608 T ^= S;
10609 }
10610 return T.isValidState();
10611 };
10612
10613 for (const auto &VAC : Values)
10614 if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
10615 return indicatePessimisticFixpoint();
10616
10617 return clampStateAndIndicateChange(getState(), T);
10618 }
10619
10620 /// See AbstractAttribute::trackStatistics()
10621 void trackStatistics() const override {
10623 }
10624};
10625
10626struct AANoFPClassReturned final
10627 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10628 AANoFPClassImpl::StateType, false,
10629 Attribute::None, false> {
10630 AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
10631 : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
10632 AANoFPClassImpl::StateType, false,
10633 Attribute::None, false>(IRP, A) {}
10634
10635 /// See AbstractAttribute::trackStatistics()
10636 void trackStatistics() const override {
10638 }
10639};
10640
10641struct AANoFPClassArgument final
10642 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
10643 AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
10644 : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10645
10646 /// See AbstractAttribute::trackStatistics()
10647 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
10648};
10649
10650struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
10651 AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
10652 : AANoFPClassFloating(IRP, A) {}
10653
10654 /// See AbstractAttribute::trackStatistics()
10655 void trackStatistics() const override {
10657 }
10658};
10659
10660struct AANoFPClassCallSiteReturned final
10661 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {
10662 AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
10663 : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl>(IRP, A) {}
10664
10665 /// See AbstractAttribute::trackStatistics()
10666 void trackStatistics() const override {
10668 }
10669};
10670
10671struct AACallEdgesImpl : public AACallEdges {
10672 AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}
10673
10674 const SetVector<Function *> &getOptimisticEdges() const override {
10675 return CalledFunctions;
10676 }
10677
10678 bool hasUnknownCallee() const override { return HasUnknownCallee; }
10679
10680 bool hasNonAsmUnknownCallee() const override {
10681 return HasUnknownCalleeNonAsm;
10682 }
10683
10684 const std::string getAsStr(Attributor *A) const override {
10685 return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
10686 std::to_string(CalledFunctions.size()) + "]";
10687 }
10688
10689 void trackStatistics() const override {}
10690
10691protected:
10692 void addCalledFunction(Function *Fn, ChangeStatus &Change) {
10693 if (CalledFunctions.insert(Fn)) {
10694 Change = ChangeStatus::CHANGED;
10695 LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
10696 << "\n");
10697 }
10698 }
10699
10700 void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
10701 if (!HasUnknownCallee)
10702 Change = ChangeStatus::CHANGED;
10703 if (NonAsm && !HasUnknownCalleeNonAsm)
10704 Change = ChangeStatus::CHANGED;
10705 HasUnknownCalleeNonAsm |= NonAsm;
10706 HasUnknownCallee = true;
10707 }
10708
10709private:
10710 /// Optimistic set of functions that might be called by this position.
10711 SetVector<Function *> CalledFunctions;
10712
10713 /// Is there any call with a unknown callee.
10714 bool HasUnknownCallee = false;
10715
10716 /// Is there any call with a unknown callee, excluding any inline asm.
10717 bool HasUnknownCalleeNonAsm = false;
10718};
10719
10720struct AACallEdgesCallSite : public AACallEdgesImpl {
10721 AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
10722 : AACallEdgesImpl(IRP, A) {}
10723 /// See AbstractAttribute::updateImpl(...).
10724 ChangeStatus updateImpl(Attributor &A) override {
10725 ChangeStatus Change = ChangeStatus::UNCHANGED;
10726
10727 auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
10728 if (Function *Fn = dyn_cast<Function>(&V)) {
10729 addCalledFunction(Fn, Change);
10730 } else {
10731 LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
10732 setHasUnknownCallee(true, Change);
10733 }
10734
10735 // Explore all values.
10736 return true;
10737 };
10738
10740 // Process any value that we might call.
10741 auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
10742 if (isa<Constant>(V)) {
10743 VisitValue(*V, CtxI);
10744 return;
10745 }
10746
10747 bool UsedAssumedInformation = false;
10748 Values.clear();
10749 if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
10750 AA::AnyScope, UsedAssumedInformation)) {
10751 Values.push_back({*V, CtxI});
10752 }
10753 for (auto &VAC : Values)
10754 VisitValue(*VAC.getValue(), VAC.getCtxI());
10755 };
10756
10757 CallBase *CB = cast<CallBase>(getCtxI());
10758
10759 if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
10760 if (IA->hasSideEffects() &&
10761 !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
10762 !hasAssumption(*CB, "ompx_no_call_asm")) {
10763 setHasUnknownCallee(false, Change);
10764 }
10765 return Change;
10766 }
10767
10768 if (CB->isIndirectCall())
10769 if (auto *IndirectCallAA = A.getAAFor<AAIndirectCallInfo>(
10770 *this, getIRPosition(), DepClassTy::OPTIONAL))
10771 if (IndirectCallAA->foreachCallee(
10772 [&](Function *Fn) { return VisitValue(*Fn, CB); }))
10773 return Change;
10774
10775 // The most simple case.
10776 ProcessCalledOperand(CB->getCalledOperand(), CB);
10777
10778 // Process callback functions.
10779 SmallVector<const Use *, 4u> CallbackUses;
10780 AbstractCallSite::getCallbackUses(*CB, CallbackUses);
10781 for (const Use *U : CallbackUses)
10782 ProcessCalledOperand(U->get(), CB);
10783
10784 return Change;
10785 }
10786};
10787
10788struct AACallEdgesFunction : public AACallEdgesImpl {
10789 AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
10790 : AACallEdgesImpl(IRP, A) {}
10791
10792 /// See AbstractAttribute::updateImpl(...).
10793 ChangeStatus updateImpl(Attributor &A) override {
10794 ChangeStatus Change = ChangeStatus::UNCHANGED;
10795
10796 auto ProcessCallInst = [&](Instruction &Inst) {
10797 CallBase &CB = cast<CallBase>(Inst);
10798
10799 auto *CBEdges = A.getAAFor<AACallEdges>(
10800 *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
10801 if (!CBEdges)
10802 return false;
10803 if (CBEdges->hasNonAsmUnknownCallee())
10804 setHasUnknownCallee(true, Change);
10805 if (CBEdges->hasUnknownCallee())
10806 setHasUnknownCallee(false, Change);
10807
10808 for (Function *F : CBEdges->getOptimisticEdges())
10809 addCalledFunction(F, Change);
10810
10811 return true;
10812 };
10813
10814 // Visit all callable instructions.
10815 bool UsedAssumedInformation = false;
10816 if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
10817 UsedAssumedInformation,
10818 /* CheckBBLivenessOnly */ true)) {
10819 // If we haven't looked at all call like instructions, assume that there
10820 // are unknown callees.
10821 setHasUnknownCallee(true, Change);
10822 }
10823
10824 return Change;
10825 }
10826};
10827
10828/// -------------------AAInterFnReachability Attribute--------------------------
10829
10830struct AAInterFnReachabilityFunction
10831 : public CachedReachabilityAA<AAInterFnReachability, Function> {
10832 using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
10833 AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
10834 : Base(IRP, A) {}
10835
10836 bool instructionCanReach(
10837 Attributor &A, const Instruction &From, const Function &To,
10838 const AA::InstExclusionSetTy *ExclusionSet) const override {
10839 assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
10840 auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);
10841
10842 RQITy StackRQI(A, From, To, ExclusionSet, false);
10843 RQITy::Reachable Result;
10844 if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
10845 return NonConstThis->isReachableImpl(A, StackRQI,
10846 /*IsTemporaryRQI=*/true);
10847 return Result == RQITy::Reachable::Yes;
10848 }
10849
10850 bool isReachableImpl(Attributor &A, RQITy &RQI,
10851 bool IsTemporaryRQI) override {
10852 const Instruction *EntryI =
10853 &RQI.From->getFunction()->getEntryBlock().front();
10854 if (EntryI != RQI.From &&
10855 !instructionCanReach(A, *EntryI, *RQI.To, nullptr))
10856 return rememberResult(A, RQITy::Reachable::No, RQI, false,
10857 IsTemporaryRQI);
10858
10859 auto CheckReachableCallBase = [&](CallBase *CB) {
10860 auto *CBEdges = A.getAAFor<AACallEdges>(
10861 *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
10862 if (!CBEdges || !CBEdges->getState().isValidState())
10863 return false;
10864 // TODO Check To backwards in this case.
10865 if (CBEdges->hasUnknownCallee())
10866 return false;
10867
10868 for (Function *Fn : CBEdges->getOptimisticEdges()) {
10869 if (Fn == RQI.To)
10870 return false;
10871
10872 if (Fn->isDeclaration()) {
10873 if (Fn->hasFnAttribute(Attribute::NoCallback))
10874 continue;
10875 // TODO Check To backwards in this case.
10876 return false;
10877 }
10878
10879 if (Fn == getAnchorScope()) {
10880 if (EntryI == RQI.From)
10881 continue;
10882 return false;
10883 }
10884
10885 const AAInterFnReachability *InterFnReachability =
10886 A.getAAFor<AAInterFnReachability>(*this, IRPosition::function(*Fn),
10887 DepClassTy::OPTIONAL);
10888
10889 const Instruction &FnFirstInst = Fn->getEntryBlock().front();
10890 if (!InterFnReachability ||
10891 InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
10892 RQI.ExclusionSet))
10893 return false;
10894 }
10895 return true;
10896 };
10897
10898 const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
10899 *this, IRPosition::function(*RQI.From->getFunction()),
10900 DepClassTy::OPTIONAL);
10901
10902 // Determine call like instructions that we can reach from the inst.
10903 auto CheckCallBase = [&](Instruction &CBInst) {
10904 // There are usually less nodes in the call graph, check inter function
10905 // reachability first.
10906 if (CheckReachableCallBase(cast<CallBase>(&CBInst)))
10907 return true;
10908 return IntraFnReachability && !IntraFnReachability->isAssumedReachable(
10909 A, *RQI.From, CBInst, RQI.ExclusionSet);
10910 };
10911
10912 bool UsedExclusionSet = /* conservative */ true;
10913 bool UsedAssumedInformation = false;
10914 if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
10915 UsedAssumedInformation,
10916 /* CheckBBLivenessOnly */ true))
10917 return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet,
10918 IsTemporaryRQI);
10919
10920 return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet,
10921 IsTemporaryRQI);
10922 }
10923
10924 void trackStatistics() const override {}
10925};
10926} // namespace
10927
10928template <typename AAType>
10929static std::optional<Constant *>
10931 const IRPosition &IRP, Type &Ty) {
10932 if (!Ty.isIntegerTy())
10933 return nullptr;
10934
10935 // This will also pass the call base context.
10936 const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
10937 if (!AA)
10938 return nullptr;
10939
10940 std::optional<Constant *> COpt = AA->getAssumedConstant(A);
10941
10942 if (!COpt.has_value()) {
10943 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10944 return std::nullopt;
10945 }
10946 if (auto *C = *COpt) {
10947 A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
10948 return C;
10949 }
10950 return nullptr;
10951}
10952
10954 Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
10956 Type &Ty = *IRP.getAssociatedType();
10957 std::optional<Value *> V;
10958 for (auto &It : Values) {
10959 V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
10960 if (V.has_value() && !*V)
10961 break;
10962 }
10963 if (!V.has_value())
10964 return UndefValue::get(&Ty);
10965 return *V;
10966}
10967
10968namespace {
10969struct AAPotentialValuesImpl : AAPotentialValues {
10970 using StateType = PotentialLLVMValuesState;
10971
10972 AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
10973 : AAPotentialValues(IRP, A) {}
10974
10975 /// See AbstractAttribute::initialize(..).
10976 void initialize(Attributor &A) override {
10977 if (A.hasSimplificationCallback(getIRPosition())) {
10978 indicatePessimisticFixpoint();
10979 return;
10980 }
10981 Value *Stripped = getAssociatedValue().stripPointerCasts();
10982 if (isa<Constant>(Stripped) && !isa<ConstantExpr>(Stripped)) {
10983 addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
10984 getAnchorScope());
10985 indicateOptimisticFixpoint();
10986 return;
10987 }
10988 AAPotentialValues::initialize(A);
10989 }
10990
10991 /// See AbstractAttribute::getAsStr().
10992 const std::string getAsStr(Attributor *A) const override {
10993 std::string Str;
10994 llvm::raw_string_ostream OS(Str);
10995 OS << getState();
10996 return Str;
10997 }
10998
10999 template <typename AAType>
11000 static std::optional<Value *> askOtherAA(Attributor &A,
11001 const AbstractAttribute &AA,
11002 const IRPosition &IRP, Type &Ty) {
11004 return &IRP.getAssociatedValue();
11005 std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
11006 if (!C)
11007 return std::nullopt;
11008 if (*C)
11009 if (auto *CC = AA::getWithType(**C, Ty))
11010 return CC;
11011 return nullptr;
11012 }
11013
11014 virtual void addValue(Attributor &A, StateType &State, Value &V,
11015 const Instruction *CtxI, AA::ValueScope S,
11016 Function *AnchorScope) const {
11017
11018 IRPosition ValIRP = IRPosition::value(V);
11019 if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
11020 for (const auto &U : CB->args()) {
11021 if (U.get() != &V)
11022 continue;
11023 ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
11024 break;
11025 }
11026 }
11027
11028 Value *VPtr = &V;
11029 if (ValIRP.getAssociatedType()->isIntegerTy()) {
11030 Type &Ty = *getAssociatedType();
11031 std::optional<Value *> SimpleV =
11032 askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
11033 if (SimpleV.has_value() && !*SimpleV) {
11034 auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
11035 *this, ValIRP, DepClassTy::OPTIONAL);
11036 if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
11037 for (const auto &It : PotentialConstantsAA->getAssumedSet())
11038 State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
11039 if (PotentialConstantsAA->undefIsContained())
11040 State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
11041 return;
11042 }
11043 }
11044 if (!SimpleV.has_value())
11045 return;
11046
11047 if (*SimpleV)
11048 VPtr = *SimpleV;
11049 }
11050
11051 if (isa<ConstantInt>(VPtr))
11052 CtxI = nullptr;
11053 if (!AA::isValidInScope(*VPtr, AnchorScope))
11055
11056 State.unionAssumed({{*VPtr, CtxI}, S});
11057 }
11058
11059 /// Helper struct to tie a value+context pair together with the scope for
11060 /// which this is the simplified version.
11061 struct ItemInfo {
11062 AA::ValueAndContext I;
11064
11065 bool operator==(const ItemInfo &II) const {
11066 return II.I == I && II.S == S;
11067 };
11068 bool operator<(const ItemInfo &II) const {
11069 return std::tie(I, S) < std::tie(II.I, II.S);
11070 };
11071 };
11072
11073 bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
11074 SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
11075 for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
11076 if (!(CS & S))
11077 continue;
11078
11079 bool UsedAssumedInformation = false;
11081 if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
11082 UsedAssumedInformation))
11083 return false;
11084
11085 for (auto &It : Values)
11086 ValueScopeMap[It] += CS;
11087 }
11088 for (auto &It : ValueScopeMap)
11089 addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
11090 AA::ValueScope(It.second), getAnchorScope());
11091
11092 return true;
11093 }
11094
11095 void giveUpOnIntraprocedural(Attributor &A) {
11096 auto NewS = StateType::getBestState(getState());
11097 for (const auto &It : getAssumedSet()) {
11098 if (It.second == AA::Intraprocedural)
11099 continue;
11100 addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
11101 AA::Interprocedural, getAnchorScope());
11102 }
11103 assert(!undefIsContained() && "Undef should be an explicit value!");
11104 addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
11105 getAnchorScope());
11106 getState() = NewS;
11107 }
11108
11109 /// See AbstractState::indicatePessimisticFixpoint(...).
11110 ChangeStatus indicatePessimisticFixpoint() override {
11111 getState() = StateType::getBestState(getState());
11112 getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
11113 AAPotentialValues::indicateOptimisticFixpoint();
11114 return ChangeStatus::CHANGED;
11115 }
11116
11117 /// See AbstractAttribute::updateImpl(...).
11118 ChangeStatus updateImpl(Attributor &A) override {
11119 return indicatePessimisticFixpoint();
11120 }
11121
11122 /// See AbstractAttribute::manifest(...).
11123 ChangeStatus manifest(Attributor &A) override {
11126 Values.clear();
11127 if (!getAssumedSimplifiedValues(A, Values, S))
11128 continue;
11129 Value &OldV = getAssociatedValue();
11130 if (isa<UndefValue>(OldV))
11131 continue;
11132 Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
11133 if (!NewV || NewV == &OldV)
11134 continue;
11135 if (getCtxI() &&
11136 !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
11137 continue;
11138 if (A.changeAfterManifest(getIRPosition(), *NewV))
11139 return ChangeStatus::CHANGED;
11140 }
11141 return ChangeStatus::UNCHANGED;
11142 }
11143
11144 bool getAssumedSimplifiedValues(
11145 Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
11146 AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
11147 if (!isValidState())
11148 return false;
11149 bool UsedAssumedInformation = false;
11150 for (const auto &It : getAssumedSet())
11151 if (It.second & S) {
11152 if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
11153 isa<SelectInst>(It.first.getValue()))) {
11154 if (A.getAssumedSimplifiedValues(
11155 IRPosition::inst(*cast<Instruction>(It.first.getValue())),
11156 this, Values, S, UsedAssumedInformation))
11157 continue;
11158 }
11159 Values.push_back(It.first);
11160 }
11161 assert(!undefIsContained() && "Undef should be an explicit value!");
11162 return true;
11163 }
11164};
11165
11166struct AAPotentialValuesFloating : AAPotentialValuesImpl {
11167 AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
11168 : AAPotentialValuesImpl(IRP, A) {}
11169
11170 /// See AbstractAttribute::updateImpl(...).
11171 ChangeStatus updateImpl(Attributor &A) override {
11172 auto AssumedBefore = getAssumed();
11173
11174 genericValueTraversal(A, &getAssociatedValue());
11175
11176 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11177 : ChangeStatus::CHANGED;
11178 }
11179
11180 /// Helper struct to remember which AAIsDead instances we actually used.
11181 struct LivenessInfo {
11182 const AAIsDead *LivenessAA = nullptr;
11183 bool AnyDead = false;
11184 };
11185
11186 /// Check if \p Cmp is a comparison we can simplify.
11187 ///
11188 /// We handle multiple cases, one in which at least one operand is an
11189 /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
11190 /// operand. Return true if successful, in that case Worklist will be updated.
11191 bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
11192 CmpInst::Predicate Pred, ItemInfo II,
11193 SmallVectorImpl<ItemInfo> &Worklist) {
11194
11195 // Simplify the operands first.
11196 bool UsedAssumedInformation = false;
11197 SmallVector<AA::ValueAndContext> LHSValues, RHSValues;
11198 auto GetSimplifiedValues = [&](Value &V,
11200 if (!A.getAssumedSimplifiedValues(
11201 IRPosition::value(V, getCallBaseContext()), this, Values,
11202 AA::Intraprocedural, UsedAssumedInformation)) {
11203 Values.clear();
11204 Values.push_back(AA::ValueAndContext{V, II.I.getCtxI()});
11205 }
11206 return Values.empty();
11207 };
11208 if (GetSimplifiedValues(*LHS, LHSValues))
11209 return true;
11210 if (GetSimplifiedValues(*RHS, RHSValues))
11211 return true;
11212
11213 LLVMContext &Ctx = LHS->getContext();
11214
11215 InformationCache &InfoCache = A.getInfoCache();
11216 Instruction *CmpI = dyn_cast<Instruction>(&Cmp);
11217 Function *F = CmpI ? CmpI->getFunction() : nullptr;
11218 const auto *DT =
11219 F ? InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F)
11220 : nullptr;
11221 const auto *TLI =
11222 F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;
11223 auto *AC =
11224 F ? InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F)
11225 : nullptr;
11226
11227 const DataLayout &DL = A.getDataLayout();
11228 SimplifyQuery Q(DL, TLI, DT, AC, CmpI);
11229
11230 auto CheckPair = [&](Value &LHSV, Value &RHSV) {
11231 if (isa<UndefValue>(LHSV) || isa<UndefValue>(RHSV)) {
11232 addValue(A, getState(), *UndefValue::get(Cmp.getType()),
11233 /* CtxI */ nullptr, II.S, getAnchorScope());
11234 return true;
11235 }
11236
11237 // Handle the trivial case first in which we don't even need to think
11238 // about null or non-null.
11239 if (&LHSV == &RHSV &&
11241 Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
11243 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11244 getAnchorScope());
11245 return true;
11246 }
11247
11248 auto *TypedLHS = AA::getWithType(LHSV, *LHS->getType());
11249 auto *TypedRHS = AA::getWithType(RHSV, *RHS->getType());
11250 if (TypedLHS && TypedRHS) {
11251 Value *NewV = simplifyCmpInst(Pred, TypedLHS, TypedRHS, Q);
11252 if (NewV && NewV != &Cmp) {
11253 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11254 getAnchorScope());
11255 return true;
11256 }
11257 }
11258
11259 // From now on we only handle equalities (==, !=).
11260 if (!CmpInst::isEquality(Pred))
11261 return false;
11262
11263 bool LHSIsNull = isa<ConstantPointerNull>(LHSV);
11264 bool RHSIsNull = isa<ConstantPointerNull>(RHSV);
11265 if (!LHSIsNull && !RHSIsNull)
11266 return false;
11267
11268 // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
11269 // non-nullptr operand and if we assume it's non-null we can conclude the
11270 // result of the comparison.
11271 assert((LHSIsNull || RHSIsNull) &&
11272 "Expected nullptr versus non-nullptr comparison at this point");
11273
11274 // The index is the operand that we assume is not null.
11275 unsigned PtrIdx = LHSIsNull;
11276 bool IsKnownNonNull;
11277 bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
11278 A, this, IRPosition::value(*(PtrIdx ? &RHSV : &LHSV)),
11279 DepClassTy::REQUIRED, IsKnownNonNull);
11280 if (!IsAssumedNonNull)
11281 return false;
11282
11283 // The new value depends on the predicate, true for != and false for ==.
11284 Constant *NewV =
11285 ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
11286 addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
11287 getAnchorScope());
11288 return true;
11289 };
11290
11291 for (auto &LHSValue : LHSValues)
11292 for (auto &RHSValue : RHSValues)
11293 if (!CheckPair(*LHSValue.getValue(), *RHSValue.getValue()))
11294 return false;
11295 return true;
11296 }
11297
11298 bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
11299 SmallVectorImpl<ItemInfo> &Worklist) {
11300 const Instruction *CtxI = II.I.getCtxI();
11301 bool UsedAssumedInformation = false;
11302
11303 std::optional<Constant *> C =
11304 A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
11305 bool NoValueYet = !C.has_value();
11306 if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
11307 return true;
11308 if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
11309 if (CI->isZero())
11310 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11311 else
11312 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11313 } else if (&SI == &getAssociatedValue()) {
11314 // We could not simplify the condition, assume both values.
11315 Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
11316 Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
11317 } else {
11318 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11319 IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
11320 if (!SimpleV.has_value())
11321 return true;
11322 if (*SimpleV) {
11323 addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
11324 return true;
11325 }
11326 return false;
11327 }
11328 return true;
11329 }
11330
11331 bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
11332 SmallVectorImpl<ItemInfo> &Worklist) {
11333 SmallSetVector<Value *, 4> PotentialCopies;
11334 SmallSetVector<Instruction *, 4> PotentialValueOrigins;
11335 bool UsedAssumedInformation = false;
11336 if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
11337 PotentialValueOrigins, *this,
11338 UsedAssumedInformation,
11339 /* OnlyExact */ true)) {
11340 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
11341 "loaded values for load instruction "
11342 << LI << "\n");
11343 return false;
11344 }
11345
11346 // Do not simplify loads that are only used in llvm.assume if we cannot also
11347 // remove all stores that may feed into the load. The reason is that the
11348 // assume is probably worth something as long as the stores are around.
11349 InformationCache &InfoCache = A.getInfoCache();
11350 if (InfoCache.isOnlyUsedByAssume(LI)) {
11351 if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
11352 if (!I || isa<AssumeInst>(I))
11353 return true;
11354 if (auto *SI = dyn_cast<StoreInst>(I))
11355 return A.isAssumedDead(SI->getOperandUse(0), this,
11356 /* LivenessAA */ nullptr,
11357 UsedAssumedInformation,
11358 /* CheckBBLivenessOnly */ false);
11359 return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
11360 UsedAssumedInformation,
11361 /* CheckBBLivenessOnly */ false);
11362 })) {
11363 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
11364 "and we cannot delete all the stores: "
11365 << LI << "\n");
11366 return false;
11367 }
11368 }
11369
11370 // Values have to be dynamically unique or we loose the fact that a
11371 // single llvm::Value might represent two runtime values (e.g.,
11372 // stack locations in different recursive calls).
11373 const Instruction *CtxI = II.I.getCtxI();
11374 bool ScopeIsLocal = (II.S & AA::Intraprocedural);
11375 bool AllLocal = ScopeIsLocal;
11376 bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
11377 AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
11378 return AA::isDynamicallyUnique(A, *this, *PC);
11379 });
11380 if (!DynamicallyUnique) {
11381 LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
11382 "values are dynamically unique: "
11383 << LI << "\n");
11384 return false;
11385 }
11386
11387 for (auto *PotentialCopy : PotentialCopies) {
11388 if (AllLocal) {
11389 Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
11390 } else {
11391 Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
11392 }
11393 }
11394 if (!AllLocal && ScopeIsLocal)
11395 addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
11396 return true;
11397 }
11398
11399 bool handlePHINode(
11400 Attributor &A, PHINode &PHI, ItemInfo II,
11401 SmallVectorImpl<ItemInfo> &Worklist,
11402 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11403 auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
11404 LivenessInfo &LI = LivenessAAs[&F];
11405 if (!LI.LivenessAA)
11406 LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
11407 DepClassTy::NONE);
11408 return LI;
11409 };
11410
11411 if (&PHI == &getAssociatedValue()) {
11412 LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
11413 const auto *CI =
11414 A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
11415 *PHI.getFunction());
11416
11417 CycleRef C;
11418 bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
11419 for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
11420 BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
11421 if (LI.LivenessAA &&
11422 LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
11423 LI.AnyDead = true;
11424 continue;
11425 }
11426 Value *V = PHI.getIncomingValue(u);
11427 if (V == &PHI)
11428 continue;
11429
11430 // If the incoming value is not the PHI but an instruction in the same
11431 // cycle we might have multiple versions of it flying around.
11432 if (CyclePHI && isa<Instruction>(V) &&
11433 (!C || CI->contains(C, cast<Instruction>(V)->getParent())))
11434 return false;
11435
11436 Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
11437 }
11438 return true;
11439 }
11440
11441 bool UsedAssumedInformation = false;
11442 std::optional<Value *> SimpleV = A.getAssumedSimplified(
11443 IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
11444 if (!SimpleV.has_value())
11445 return true;
11446 if (!(*SimpleV))
11447 return false;
11448 addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
11449 return true;
11450 }
11451
11452 /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
11453 /// simplify any operand of the instruction \p I. Return true if successful,
11454 /// in that case Worklist will be updated.
11455 bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
11456 SmallVectorImpl<ItemInfo> &Worklist) {
11457 bool SomeSimplified = false;
11458 bool UsedAssumedInformation = false;
11459
11460 SmallVector<Value *, 8> NewOps(I.getNumOperands());
11461 int Idx = 0;
11462 for (Value *Op : I.operands()) {
11463 const auto &SimplifiedOp = A.getAssumedSimplified(
11464 IRPosition::value(*Op, getCallBaseContext()), *this,
11465 UsedAssumedInformation, AA::Intraprocedural);
11466 // If we are not sure about any operand we are not sure about the entire
11467 // instruction, we'll wait.
11468 if (!SimplifiedOp.has_value())
11469 return true;
11470
11471 if (*SimplifiedOp)
11472 NewOps[Idx] = *SimplifiedOp;
11473 else
11474 NewOps[Idx] = Op;
11475
11476 SomeSimplified |= (NewOps[Idx] != Op);
11477 ++Idx;
11478 }
11479
11480 // We won't bother with the InstSimplify interface if we didn't simplify any
11481 // operand ourselves.
11482 if (!SomeSimplified)
11483 return false;
11484
11485 InformationCache &InfoCache = A.getInfoCache();
11486 Function *F = I.getFunction();
11487 const auto *DT =
11488 InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
11489 const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
11490 auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
11491
11492 const DataLayout &DL = I.getDataLayout();
11493 SimplifyQuery Q(DL, TLI, DT, AC, &I);
11494 Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
11495 if (!NewV || NewV == &I)
11496 return false;
11497
11498 LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
11499 << *NewV << "\n");
11500 Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
11501 return true;
11502 }
11503
11505 Attributor &A, Instruction &I, ItemInfo II,
11506 SmallVectorImpl<ItemInfo> &Worklist,
11507 SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
11508 if (auto *CI = dyn_cast<CmpInst>(&I))
11509 return handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
11510 CI->getPredicate(), II, Worklist);
11511
11512 switch (I.getOpcode()) {
11513 case Instruction::Select:
11514 return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
11515 case Instruction::PHI:
11516 return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
11517 case Instruction::Load:
11518 return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
11519 default:
11520 return handleGenericInst(A, I, II, Worklist);
11521 };
11522 return false;
11523 }
11524
11525 void genericValueTraversal(Attributor &A, Value *InitialV) {
11526 SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;
11527
11528 SmallSet<ItemInfo, 16> Visited;
11530 Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});
11531
11532 int Iteration = 0;
11533 do {
11534 ItemInfo II = Worklist.pop_back_val();
11535 Value *V = II.I.getValue();
11536 assert(V);
11537 const Instruction *CtxI = II.I.getCtxI();
11538 AA::ValueScope S = II.S;
11539
11540 // Check if we should process the current value. To prevent endless
11541 // recursion keep a record of the values we followed!
11542 if (!Visited.insert(II).second)
11543 continue;
11544
11545 // Make sure we limit the compile time for complex expressions.
11546 if (Iteration++ >= MaxPotentialValuesIterations) {
11547 LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
11548 << Iteration << "!\n");
11549 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11550 continue;
11551 }
11552
11553 // Explicitly look through calls with a "returned" attribute if we do
11554 // not have a pointer as stripPointerCasts only works on them.
11555 Value *NewV = nullptr;
11556 if (V->getType()->isPointerTy()) {
11557 NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
11558 } else {
11559 if (auto *CB = dyn_cast<CallBase>(V))
11560 if (auto *Callee =
11562 for (Argument &Arg : Callee->args())
11563 if (Arg.hasReturnedAttr()) {
11564 NewV = CB->getArgOperand(Arg.getArgNo());
11565 break;
11566 }
11567 }
11568 }
11569 if (NewV && NewV != V) {
11570 Worklist.push_back({{*NewV, CtxI}, S});
11571 continue;
11572 }
11573
11574 if (auto *I = dyn_cast<Instruction>(V)) {
11575 if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
11576 continue;
11577 }
11578
11579 if (V != InitialV || isa<Argument>(V))
11580 if (recurseForValue(A, IRPosition::value(*V), II.S))
11581 continue;
11582
11583 // If we haven't stripped anything we give up.
11584 if (V == InitialV && CtxI == getCtxI()) {
11585 indicatePessimisticFixpoint();
11586 return;
11587 }
11588
11589 addValue(A, getState(), *V, CtxI, S, getAnchorScope());
11590 } while (!Worklist.empty());
11591
11592 // If we actually used liveness information so we have to record a
11593 // dependence.
11594 for (auto &It : LivenessAAs)
11595 if (It.second.AnyDead)
11596 A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
11597 }
11598
11599 /// See AbstractAttribute::trackStatistics()
11600 void trackStatistics() const override {
11601 STATS_DECLTRACK_FLOATING_ATTR(potential_values)
11602 }
11603};
11604
11605struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
11606 using Base = AAPotentialValuesImpl;
11607 AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
11608 : Base(IRP, A) {}
11609
11610 /// See AbstractAttribute::initialize(..).
11611 void initialize(Attributor &A) override {
11612 auto &Arg = cast<Argument>(getAssociatedValue());
11614 indicatePessimisticFixpoint();
11615 }
11616
11617 /// See AbstractAttribute::updateImpl(...).
11618 ChangeStatus updateImpl(Attributor &A) override {
11619 auto AssumedBefore = getAssumed();
11620
11621 unsigned ArgNo = getCalleeArgNo();
11622
11623 bool UsedAssumedInformation = false;
11625 auto CallSitePred = [&](AbstractCallSite ACS) {
11626 const auto CSArgIRP = IRPosition::callsite_argument(ACS, ArgNo);
11627 if (CSArgIRP.getPositionKind() == IRP_INVALID)
11628 return false;
11629
11630 if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
11632 UsedAssumedInformation))
11633 return false;
11634
11635 return isValidState();
11636 };
11637
11638 if (!A.checkForAllCallSites(CallSitePred, *this,
11639 /* RequireAllCallSites */ true,
11640 UsedAssumedInformation))
11641 return indicatePessimisticFixpoint();
11642
11643 Function *Fn = getAssociatedFunction();
11644 bool AnyNonLocal = false;
11645 for (auto &It : Values) {
11646 if (isa<Constant>(It.getValue())) {
11647 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11648 getAnchorScope());
11649 continue;
11650 }
11651 if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
11652 return indicatePessimisticFixpoint();
11653
11654 if (auto *Arg = dyn_cast<Argument>(It.getValue()))
11655 if (Arg->getParent() == Fn) {
11656 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
11657 getAnchorScope());
11658 continue;
11659 }
11660 addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
11661 getAnchorScope());
11662 AnyNonLocal = true;
11663 }
11664 assert(!undefIsContained() && "Undef should be an explicit value!");
11665 if (AnyNonLocal)
11666 giveUpOnIntraprocedural(A);
11667
11668 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11669 : ChangeStatus::CHANGED;
11670 }
11671
11672 /// See AbstractAttribute::trackStatistics()
11673 void trackStatistics() const override {
11674 STATS_DECLTRACK_ARG_ATTR(potential_values)
11675 }
11676};
11677
11678struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
11679 using Base = AAPotentialValuesFloating;
11680 AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
11681 : Base(IRP, A) {}
11682
11683 /// See AbstractAttribute::initialize(..).
11684 void initialize(Attributor &A) override {
11685 Function *F = getAssociatedFunction();
11686 if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
11687 indicatePessimisticFixpoint();
11688 return;
11689 }
11690
11691 for (Argument &Arg : F->args())
11692 if (Arg.hasReturnedAttr()) {
11693 addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
11694 ReturnedArg = &Arg;
11695 break;
11696 }
11697 if (!A.isFunctionIPOAmendable(*F) ||
11698 A.hasSimplificationCallback(getIRPosition())) {
11699 if (!ReturnedArg)
11700 indicatePessimisticFixpoint();
11701 else
11702 indicateOptimisticFixpoint();
11703 }
11704 }
11705
11706 /// See AbstractAttribute::updateImpl(...).
11707 ChangeStatus updateImpl(Attributor &A) override {
11708 auto AssumedBefore = getAssumed();
11709 bool UsedAssumedInformation = false;
11710
11712 Function *AnchorScope = getAnchorScope();
11713 auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
11714 bool AddValues) {
11716 Values.clear();
11717 if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
11718 UsedAssumedInformation,
11719 /* RecurseForSelectAndPHI */ true))
11720 return false;
11721 if (!AddValues)
11722 continue;
11723
11724 bool AllInterAreIntra = false;
11725 if (S == AA::Interprocedural)
11726 AllInterAreIntra =
11727 llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
11728 return AA::isValidInScope(*VAC.getValue(), AnchorScope);
11729 });
11730
11731 for (const AA::ValueAndContext &VAC : Values) {
11732 addValue(A, getState(), *VAC.getValue(),
11733 VAC.getCtxI() ? VAC.getCtxI() : CtxI,
11734 AllInterAreIntra ? AA::AnyScope : S, AnchorScope);
11735 }
11736 if (AllInterAreIntra)
11737 break;
11738 }
11739 return true;
11740 };
11741
11742 if (ReturnedArg) {
11743 HandleReturnedValue(*ReturnedArg, nullptr, true);
11744 } else {
11745 auto RetInstPred = [&](Instruction &RetI) {
11746 bool AddValues = true;
11747 if (isa<PHINode>(RetI.getOperand(0)) ||
11748 isa<SelectInst>(RetI.getOperand(0))) {
11749 addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
11750 AnchorScope);
11751 AddValues = false;
11752 }
11753 return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
11754 };
11755
11756 if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11757 UsedAssumedInformation,
11758 /* CheckBBLivenessOnly */ true))
11759 return indicatePessimisticFixpoint();
11760 }
11761
11762 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11763 : ChangeStatus::CHANGED;
11764 }
11765
11766 ChangeStatus manifest(Attributor &A) override {
11767 if (ReturnedArg)
11768 return ChangeStatus::UNCHANGED;
11770 if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
11771 /* RecurseForSelectAndPHI */ true))
11772 return ChangeStatus::UNCHANGED;
11773 Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
11774 if (!NewVal)
11775 return ChangeStatus::UNCHANGED;
11776
11777 ChangeStatus Changed = ChangeStatus::UNCHANGED;
11778 if (auto *Arg = dyn_cast<Argument>(NewVal)) {
11779 STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
11780 "Number of function with unique return");
11781 Changed |= A.manifestAttrs(
11783 {Attribute::get(Arg->getContext(), Attribute::Returned)});
11784 STATS_DECLTRACK_ARG_ATTR(returned);
11785 }
11786
11787 auto RetInstPred = [&](Instruction &RetI) {
11788 Value *RetOp = RetI.getOperand(0);
11789 if (isa<UndefValue>(RetOp) || RetOp == NewVal)
11790 return true;
11791 if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
11792 if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
11793 Changed = ChangeStatus::CHANGED;
11794 return true;
11795 };
11796 bool UsedAssumedInformation = false;
11797 (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
11798 UsedAssumedInformation,
11799 /* CheckBBLivenessOnly */ true);
11800 return Changed;
11801 }
11802
11803 ChangeStatus indicatePessimisticFixpoint() override {
11804 return AAPotentialValues::indicatePessimisticFixpoint();
11805 }
11806
11807 /// See AbstractAttribute::trackStatistics()
11808 void trackStatistics() const override{
11809 STATS_DECLTRACK_FNRET_ATTR(potential_values)}
11810
11811 /// The argumented with an existing `returned` attribute.
11812 Argument *ReturnedArg = nullptr;
11813};
11814
11815struct AAPotentialValuesFunction : AAPotentialValuesImpl {
11816 AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
11817 : AAPotentialValuesImpl(IRP, A) {}
11818
11819 /// See AbstractAttribute::updateImpl(...).
11820 ChangeStatus updateImpl(Attributor &A) override {
11821 llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
11822 "not be called");
11823 }
11824
11825 /// See AbstractAttribute::trackStatistics()
11826 void trackStatistics() const override {
11827 STATS_DECLTRACK_FN_ATTR(potential_values)
11828 }
11829};
11830
11831struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
11832 AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
11833 : AAPotentialValuesFunction(IRP, A) {}
11834
11835 /// See AbstractAttribute::trackStatistics()
11836 void trackStatistics() const override {
11837 STATS_DECLTRACK_CS_ATTR(potential_values)
11838 }
11839};
11840
11841struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
11842 AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
11843 : AAPotentialValuesImpl(IRP, A) {}
11844
11845 /// See AbstractAttribute::updateImpl(...).
11846 ChangeStatus updateImpl(Attributor &A) override {
11847 auto AssumedBefore = getAssumed();
11848
11849 Function *Callee = getAssociatedFunction();
11850 if (!Callee)
11851 return indicatePessimisticFixpoint();
11852
11853 bool UsedAssumedInformation = false;
11854 auto *CB = cast<CallBase>(getCtxI());
11855 if (CB->isMustTailCall() &&
11856 !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
11857 UsedAssumedInformation))
11858 return indicatePessimisticFixpoint();
11859
11860 Function *Caller = CB->getCaller();
11861
11862 auto AddScope = [&](AA::ValueScope S) {
11864 if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
11865 Values, S, UsedAssumedInformation))
11866 return false;
11867
11868 for (auto &It : Values) {
11869 Value *V = It.getValue();
11870 std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
11871 V, *CB, *this, UsedAssumedInformation);
11872 if (!CallerV.has_value()) {
11873 // Nothing to do as long as no value was determined.
11874 continue;
11875 }
11876 V = *CallerV ? *CallerV : V;
11877 if (*CallerV && AA::isDynamicallyUnique(A, *this, *V)) {
11878 if (recurseForValue(A, IRPosition::value(*V), S))
11879 continue;
11880 }
11881 if (S == AA::Intraprocedural && !AA::isValidInScope(*V, Caller)) {
11882 giveUpOnIntraprocedural(A);
11883 return true;
11884 }
11885 addValue(A, getState(), *V, CB, S, getAnchorScope());
11886 }
11887 return true;
11888 };
11889 if (!AddScope(AA::Intraprocedural))
11890 return indicatePessimisticFixpoint();
11891 if (!AddScope(AA::Interprocedural))
11892 return indicatePessimisticFixpoint();
11893 return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
11894 : ChangeStatus::CHANGED;
11895 }
11896
11897 ChangeStatus indicatePessimisticFixpoint() override {
11898 return AAPotentialValues::indicatePessimisticFixpoint();
11899 }
11900
11901 /// See AbstractAttribute::trackStatistics()
11902 void trackStatistics() const override {
11903 STATS_DECLTRACK_CSRET_ATTR(potential_values)
11904 }
11905};
11906
11907struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
11908 AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
11909 : AAPotentialValuesFloating(IRP, A) {}
11910
11911 /// See AbstractAttribute::trackStatistics()
11912 void trackStatistics() const override {
11913 STATS_DECLTRACK_CSARG_ATTR(potential_values)
11914 }
11915};
11916} // namespace
11917
11918/// ---------------------- Assumption Propagation ------------------------------
11919namespace {
11920struct AAAssumptionInfoImpl : public AAAssumptionInfo {
11921 AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
11922 const DenseSet<StringRef> &Known)
11923 : AAAssumptionInfo(IRP, A, Known) {}
11924
11925 /// See AbstractAttribute::manifest(...).
11926 ChangeStatus manifest(Attributor &A) override {
11927 // Don't manifest a universal set if it somehow made it here.
11928 if (getKnown().isUniversal())
11929 return ChangeStatus::UNCHANGED;
11930
11931 const IRPosition &IRP = getIRPosition();
11932 SmallVector<StringRef, 0> Set(getAssumed().getSet().begin(),
11933 getAssumed().getSet().end());
11934 llvm::sort(Set);
11935 return A.manifestAttrs(IRP,
11936 Attribute::get(IRP.getAnchorValue().getContext(),
11938 llvm::join(Set, ",")),
11939 /*ForceReplace=*/true);
11940 }
11941
11942 bool hasAssumption(const StringRef Assumption) const override {
11943 return isValidState() && setContains(Assumption);
11944 }
11945
11946 /// See AbstractAttribute::getAsStr()
11947 const std::string getAsStr(Attributor *A) const override {
11948 const SetContents &Known = getKnown();
11949 const SetContents &Assumed = getAssumed();
11950
11951 SmallVector<StringRef, 0> Set(Known.getSet().begin(), Known.getSet().end());
11952 llvm::sort(Set);
11953 const std::string KnownStr = llvm::join(Set, ",");
11954
11955 std::string AssumedStr = "Universal";
11956 if (!Assumed.isUniversal()) {
11957 Set.assign(Assumed.getSet().begin(), Assumed.getSet().end());
11958 AssumedStr = llvm::join(Set, ",");
11959 }
11960 return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
11961 }
11962};
11963
11964/// Propagates assumption information from parent functions to all of their
11965/// successors. An assumption can be propagated if the containing function
11966/// dominates the called function.
11967///
11968/// We start with a "known" set of assumptions already valid for the associated
11969/// function and an "assumed" set that initially contains all possible
11970/// assumptions. The assumed set is inter-procedurally updated by narrowing its
11971/// contents as concrete values are known. The concrete values are seeded by the
11972/// first nodes that are either entries into the call graph, or contains no
11973/// assumptions. Each node is updated as the intersection of the assumed state
11974/// with all of its predecessors.
11975struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
11976 AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
11977 : AAAssumptionInfoImpl(IRP, A,
11978 getAssumptions(*IRP.getAssociatedFunction())) {}
11979
11980 /// See AbstractAttribute::updateImpl(...).
11981 ChangeStatus updateImpl(Attributor &A) override {
11982 bool Changed = false;
11983
11984 auto CallSitePred = [&](AbstractCallSite ACS) {
11985 const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
11986 *this, IRPosition::callsite_function(*ACS.getInstruction()),
11987 DepClassTy::REQUIRED);
11988 if (!AssumptionAA)
11989 return false;
11990 // Get the set of assumptions shared by all of this function's callers.
11991 Changed |= getIntersection(AssumptionAA->getAssumed());
11992 return !getAssumed().empty() || !getKnown().empty();
11993 };
11994
11995 bool UsedAssumedInformation = false;
11996 // Get the intersection of all assumptions held by this node's predecessors.
11997 // If we don't know all the call sites then this is either an entry into the
11998 // call graph or an empty node. This node is known to only contain its own
11999 // assumptions and can be propagated to its successors.
12000 if (!A.checkForAllCallSites(CallSitePred, *this, true,
12001 UsedAssumedInformation))
12002 return indicatePessimisticFixpoint();
12003
12004 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12005 }
12006
12007 void trackStatistics() const override {}
12008};
12009
12010/// Assumption Info defined for call sites.
12011struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {
12012
12013 AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
12014 : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}
12015
12016 /// See AbstractAttribute::initialize(...).
12017 void initialize(Attributor &A) override {
12018 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
12019 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
12020 }
12021
12022 /// See AbstractAttribute::updateImpl(...).
12023 ChangeStatus updateImpl(Attributor &A) override {
12024 const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
12025 auto *AssumptionAA =
12026 A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
12027 if (!AssumptionAA)
12028 return indicatePessimisticFixpoint();
12029 bool Changed = getIntersection(AssumptionAA->getAssumed());
12030 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12031 }
12032
12033 /// See AbstractAttribute::trackStatistics()
12034 void trackStatistics() const override {}
12035
12036private:
12037 /// Helper to initialized the known set as all the assumptions this call and
12038 /// the callee contain.
12039 DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
12040 const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
12041 auto Assumptions = getAssumptions(CB);
12042 if (const Function *F = CB.getCaller())
12043 set_union(Assumptions, getAssumptions(*F));
12044 if (Function *F = IRP.getAssociatedFunction())
12045 set_union(Assumptions, getAssumptions(*F));
12046 return Assumptions;
12047 }
12048};
12049} // namespace
12050
12052 return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
12053 A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
12054}
12055
12057
12058/// ------------------------ UnderlyingObjects ---------------------------------
12059
12060namespace {
12061struct AAUnderlyingObjectsImpl
12062 : StateWrapper<BooleanState, AAUnderlyingObjects> {
12064 AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}
12065
12066 /// See AbstractAttribute::getAsStr().
12067 const std::string getAsStr(Attributor *A) const override {
12068 if (!isValidState())
12069 return "<invalid>";
12070 std::string Str;
12072 OS << "underlying objects: inter " << InterAssumedUnderlyingObjects.size()
12073 << " objects, intra " << IntraAssumedUnderlyingObjects.size()
12074 << " objects.\n";
12075 if (!InterAssumedUnderlyingObjects.empty()) {
12076 OS << "inter objects:\n";
12077 for (auto *Obj : InterAssumedUnderlyingObjects)
12078 OS << *Obj << '\n';
12079 }
12080 if (!IntraAssumedUnderlyingObjects.empty()) {
12081 OS << "intra objects:\n";
12082 for (auto *Obj : IntraAssumedUnderlyingObjects)
12083 OS << *Obj << '\n';
12084 }
12085 return Str;
12086 }
12087
12088 /// See AbstractAttribute::trackStatistics()
12089 void trackStatistics() const override {}
12090
12091 /// See AbstractAttribute::updateImpl(...).
12092 ChangeStatus updateImpl(Attributor &A) override {
12093 auto &Ptr = getAssociatedValue();
12094
12095 bool UsedAssumedInformation = false;
12096 auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
12098 SmallPtrSet<Value *, 8> SeenObjects;
12100
12101 if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
12102 Scope, UsedAssumedInformation))
12103 return UnderlyingObjects.insert(&Ptr);
12104
12105 bool Changed = false;
12106
12107 for (unsigned I = 0; I < Values.size(); ++I) {
12108 auto &VAC = Values[I];
12109 auto *Obj = VAC.getValue();
12110 Value *UO = getUnderlyingObject(Obj);
12111 if (!SeenObjects.insert(UO ? UO : Obj).second)
12112 continue;
12113 if (UO && UO != Obj) {
12114 if (isa<AllocaInst>(UO) || isa<GlobalValue>(UO)) {
12115 Changed |= UnderlyingObjects.insert(UO);
12116 continue;
12117 }
12118
12119 const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
12120 *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
12121 auto Pred = [&](Value &V) {
12122 if (&V == UO)
12123 Changed |= UnderlyingObjects.insert(UO);
12124 else
12125 Values.emplace_back(V, nullptr);
12126 return true;
12127 };
12128
12129 if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
12131 "The forall call should not return false at this position");
12132 UsedAssumedInformation |= !OtherAA->getState().isAtFixpoint();
12133 continue;
12134 }
12135
12136 if (isa<SelectInst>(Obj)) {
12137 Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope,
12138 UsedAssumedInformation);
12139 continue;
12140 }
12141 if (auto *PHI = dyn_cast<PHINode>(Obj)) {
12142 // Explicitly look through PHIs as we do not care about dynamically
12143 // uniqueness.
12144 for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
12145 Changed |=
12146 handleIndirect(A, *PHI->getIncomingValue(u), UnderlyingObjects,
12147 Scope, UsedAssumedInformation);
12148 }
12149 continue;
12150 }
12151
12152 Changed |= UnderlyingObjects.insert(Obj);
12153 }
12154
12155 return Changed;
12156 };
12157
12158 bool Changed = false;
12159 Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
12160 Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);
12161 if (!UsedAssumedInformation)
12162 indicateOptimisticFixpoint();
12163 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
12164 }
12165
12166 bool forallUnderlyingObjects(
12167 function_ref<bool(Value &)> Pred,
12168 AA::ValueScope Scope = AA::Interprocedural) const override {
12169 if (!isValidState())
12170 return Pred(getAssociatedValue());
12171
12172 auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
12173 ? IntraAssumedUnderlyingObjects
12174 : InterAssumedUnderlyingObjects;
12175 for (Value *Obj : AssumedUnderlyingObjects)
12176 if (!Pred(*Obj))
12177 return false;
12178
12179 return true;
12180 }
12181
12182private:
12183 /// Handle the case where the value is not the actual underlying value, such
12184 /// as a phi node or a select instruction.
12185 bool handleIndirect(Attributor &A, Value &V,
12186 SmallSetVector<Value *, 8> &UnderlyingObjects,
12187 AA::ValueScope Scope, bool &UsedAssumedInformation) {
12188 bool Changed = false;
12189 const auto *AA = A.getAAFor<AAUnderlyingObjects>(
12190 *this, IRPosition::value(V), DepClassTy::OPTIONAL);
12191 auto Pred = [&](Value &V) {
12192 Changed |= UnderlyingObjects.insert(&V);
12193 return true;
12194 };
12195 if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
12197 "The forall call should not return false at this position");
12198 UsedAssumedInformation |= !AA->getState().isAtFixpoint();
12199 return Changed;
12200 }
12201
12202 /// All the underlying objects collected so far via intra procedural scope.
12203 SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
12204 /// All the underlying objects collected so far via inter procedural scope.
12205 SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
12206};
12207
12208struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
12209 AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
12210 : AAUnderlyingObjectsImpl(IRP, A) {}
12211};
12212
12213struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
12214 AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
12215 : AAUnderlyingObjectsImpl(IRP, A) {}
12216};
12217
12218struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
12219 AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
12220 : AAUnderlyingObjectsImpl(IRP, A) {}
12221};
12222
12223struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
12224 AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
12225 : AAUnderlyingObjectsImpl(IRP, A) {}
12226};
12227
12228struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
12229 AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
12230 : AAUnderlyingObjectsImpl(IRP, A) {}
12231};
12232
12233struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
12234 AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
12235 : AAUnderlyingObjectsImpl(IRP, A) {}
12236};
12237
12238struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
12239 AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
12240 : AAUnderlyingObjectsImpl(IRP, A) {}
12241};
12242} // namespace
12243
12244/// ------------------------ Global Value Info -------------------------------
12245namespace {
12246struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {
12247 AAGlobalValueInfoFloating(const IRPosition &IRP, Attributor &A)
12248 : AAGlobalValueInfo(IRP, A) {}
12249
12250 /// See AbstractAttribute::initialize(...).
12251 void initialize(Attributor &A) override {}
12252
12253 bool checkUse(Attributor &A, const Use &U, bool &Follow,
12254 SmallVectorImpl<const Value *> &Worklist) {
12255 Instruction *UInst = dyn_cast<Instruction>(U.getUser());
12256 if (!UInst) {
12257 // Outside a closed world, code outside the module can read an
12258 // externally visible global, so the value escapes through it.
12259 if (auto *GV = dyn_cast<GlobalValue>(U.getUser()))
12260 if (!GV->hasLocalLinkage() && !A.isClosedWorldModule())
12261 return false;
12262 Follow = true;
12263 return true;
12264 }
12265
12266 LLVM_DEBUG(dbgs() << "[AAGlobalValueInfo] Check use: " << *U.get() << " in "
12267 << *UInst << "\n");
12268
12269 if (auto *Cmp = dyn_cast<ICmpInst>(U.getUser())) {
12270 int Idx = &Cmp->getOperandUse(0) == &U;
12271 if (isa<Constant>(Cmp->getOperand(Idx)))
12272 return true;
12273 return U == &getAnchorValue();
12274 }
12275
12276 // Explicitly catch return instructions.
12277 if (isa<ReturnInst>(UInst)) {
12278 auto CallSitePred = [&](AbstractCallSite ACS) {
12279 Worklist.push_back(ACS.getInstruction());
12280 return true;
12281 };
12282 bool UsedAssumedInformation = false;
12283 // TODO: We should traverse the uses or add a "non-call-site" CB.
12284 if (!A.checkForAllCallSites(CallSitePred, *UInst->getFunction(),
12285 /*RequireAllCallSites=*/true, this,
12286 UsedAssumedInformation))
12287 return false;
12288 return true;
12289 }
12290
12291 // For now we only use special logic for call sites. However, the tracker
12292 // itself knows about a lot of other non-capturing cases already.
12293 auto *CB = dyn_cast<CallBase>(UInst);
12294 if (!CB)
12295 return false;
12296 // Direct calls are OK uses.
12297 if (CB->isCallee(&U))
12298 return true;
12299 // Non-argument uses are scary.
12300 if (!CB->isArgOperand(&U))
12301 return false;
12302 // TODO: Iterate callees.
12303 auto *Fn = dyn_cast<Function>(CB->getCalledOperand());
12304 if (!Fn || !A.isFunctionIPOAmendable(*Fn))
12305 return false;
12306
12307 unsigned ArgNo = CB->getArgOperandNo(&U);
12308 Worklist.push_back(Fn->getArg(ArgNo));
12309 return true;
12310 }
12311
12312 ChangeStatus updateImpl(Attributor &A) override {
12313 unsigned NumUsesBefore = Uses.size();
12314
12315 SmallPtrSet<const Value *, 8> Visited;
12317 Worklist.push_back(&getAnchorValue());
12318
12319 auto UsePred = [&](const Use &U, bool &Follow) -> bool {
12320 Uses.insert(&U);
12321 // TODO(captures): Make this more precise.
12322 UseCaptureInfo CI = DetermineUseCaptureKind(U, /*Base=*/nullptr);
12323 if (CI.isPassthrough()) {
12324 Follow = true;
12325 return true;
12326 }
12327 return checkUse(A, U, Follow, Worklist);
12328 };
12329 auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
12330 Uses.insert(&OldU);
12331 return true;
12332 };
12333
12334 while (!Worklist.empty()) {
12335 const Value *V = Worklist.pop_back_val();
12336 if (!Visited.insert(V).second)
12337 continue;
12338 if (!A.checkForAllUses(UsePred, *this, *V,
12339 /* CheckBBLivenessOnly */ true,
12340 DepClassTy::OPTIONAL,
12341 /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
12342 return indicatePessimisticFixpoint();
12343 }
12344 }
12345
12346 return Uses.size() == NumUsesBefore ? ChangeStatus::UNCHANGED
12347 : ChangeStatus::CHANGED;
12348 }
12349
12350 bool isPotentialUse(const Use &U) const override {
12351 return !isValidState() || Uses.contains(&U);
12352 }
12353
12354 /// See AbstractAttribute::manifest(...).
12355 ChangeStatus manifest(Attributor &A) override {
12356 return ChangeStatus::UNCHANGED;
12357 }
12358
12359 /// See AbstractAttribute::getAsStr().
12360 const std::string getAsStr(Attributor *A) const override {
12361 return "[" + std::to_string(Uses.size()) + " uses]";
12362 }
12363
12364 void trackStatistics() const override {
12365 STATS_DECLTRACK_FLOATING_ATTR(GlobalValuesTracked);
12366 }
12367
12368private:
12369 /// Set of (transitive) uses of this GlobalValue.
12370 SmallPtrSet<const Use *, 8> Uses;
12371};
12372} // namespace
12373
12374/// ------------------------ Indirect Call Info -------------------------------
12375namespace {
12376struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {
12377 AAIndirectCallInfoCallSite(const IRPosition &IRP, Attributor &A)
12378 : AAIndirectCallInfo(IRP, A) {}
12379
12380 /// See AbstractAttribute::initialize(...).
12381 void initialize(Attributor &A) override {
12382 auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees);
12383 if (!MD && !A.isClosedWorldModule())
12384 return;
12385
12386 if (MD) {
12387 for (const auto &Op : MD->operands())
12389 PotentialCallees.insert(Callee);
12390 } else if (A.isClosedWorldModule()) {
12391 ArrayRef<Function *> IndirectlyCallableFunctions =
12392 A.getInfoCache().getIndirectlyCallableFunctions(A);
12393 PotentialCallees.insert_range(IndirectlyCallableFunctions);
12394 }
12395
12396 if (PotentialCallees.empty())
12397 indicateOptimisticFixpoint();
12398 }
12399
12400 ChangeStatus updateImpl(Attributor &A) override {
12401 CallBase *CB = cast<CallBase>(getCtxI());
12402 const Use &CalleeUse = CB->getCalledOperandUse();
12403 Value *FP = CB->getCalledOperand();
12404
12405 SmallSetVector<Function *, 4> AssumedCalleesNow;
12406 bool AllCalleesKnownNow = AllCalleesKnown;
12407
12408 auto CheckPotentialCalleeUse = [&](Function &PotentialCallee,
12409 bool &UsedAssumedInformation) {
12410 const auto *GIAA = A.getAAFor<AAGlobalValueInfo>(
12411 *this, IRPosition::value(PotentialCallee), DepClassTy::OPTIONAL);
12412 if (!GIAA || GIAA->isPotentialUse(CalleeUse))
12413 return true;
12414 UsedAssumedInformation = !GIAA->isAtFixpoint();
12415 return false;
12416 };
12417
12418 auto AddPotentialCallees = [&]() {
12419 for (auto *PotentialCallee : PotentialCallees) {
12420 bool UsedAssumedInformation = false;
12421 if (CheckPotentialCalleeUse(*PotentialCallee, UsedAssumedInformation))
12422 AssumedCalleesNow.insert(PotentialCallee);
12423 }
12424 };
12425
12426 // Use simplification to find potential callees, if !callees was present,
12427 // fallback to that set if necessary.
12428 bool UsedAssumedInformation = false;
12430 if (!A.getAssumedSimplifiedValues(IRPosition::value(*FP), this, Values,
12431 AA::ValueScope::AnyScope,
12432 UsedAssumedInformation)) {
12433 if (PotentialCallees.empty())
12434 return indicatePessimisticFixpoint();
12435 AddPotentialCallees();
12436 }
12437
12438 // Try to find a reason for \p Fn not to be a potential callee. If none was
12439 // found, add it to the assumed callees set.
12440 auto CheckPotentialCallee = [&](Function &Fn) {
12441 if (!PotentialCallees.empty() && !PotentialCallees.count(&Fn))
12442 return false;
12443
12444 auto &CachedResult = FilterResults[&Fn];
12445 if (CachedResult.has_value())
12446 return CachedResult.value();
12447
12448 bool UsedAssumedInformation = false;
12449 if (!CheckPotentialCalleeUse(Fn, UsedAssumedInformation)) {
12450 if (!UsedAssumedInformation)
12451 CachedResult = false;
12452 return false;
12453 }
12454
12455 int NumFnArgs = Fn.arg_size();
12456 int NumCBArgs = CB->arg_size();
12457
12458 // Check if any excess argument (which we fill up with poison) is known to
12459 // be UB on undef.
12460 for (int I = NumCBArgs; I < NumFnArgs; ++I) {
12461 bool IsKnown = false;
12463 A, this, IRPosition::argument(*Fn.getArg(I)),
12464 DepClassTy::OPTIONAL, IsKnown)) {
12465 if (IsKnown)
12466 CachedResult = false;
12467 return false;
12468 }
12469 }
12470
12471 CachedResult = true;
12472 return true;
12473 };
12474
12475 // Check simplification result, prune known UB callees, also restrict it to
12476 // the !callees set, if present.
12477 for (auto &VAC : Values) {
12478 if (isa<UndefValue>(VAC.getValue()))
12479 continue;
12481 VAC.getValue()->getType()->getPointerAddressSpace() == 0)
12482 continue;
12483 // TODO: Check for known UB, e.g., poison + noundef.
12484 if (auto *VACFn = dyn_cast<Function>(VAC.getValue())) {
12485 if (CheckPotentialCallee(*VACFn))
12486 AssumedCalleesNow.insert(VACFn);
12487 continue;
12488 }
12489 if (!PotentialCallees.empty()) {
12490 AddPotentialCallees();
12491 break;
12492 }
12493 AllCalleesKnownNow = false;
12494 }
12495
12496 if (AssumedCalleesNow == AssumedCallees &&
12497 AllCalleesKnown == AllCalleesKnownNow)
12498 return ChangeStatus::UNCHANGED;
12499
12500 std::swap(AssumedCallees, AssumedCalleesNow);
12501 AllCalleesKnown = AllCalleesKnownNow;
12502 return ChangeStatus::CHANGED;
12503 }
12504
12505 /// See AbstractAttribute::manifest(...).
12506 ChangeStatus manifest(Attributor &A) override {
12507 // If we can't specialize at all, give up now.
12508 if (!AllCalleesKnown && AssumedCallees.empty())
12509 return ChangeStatus::UNCHANGED;
12510
12511 CallBase *CB = cast<CallBase>(getCtxI());
12512 bool UsedAssumedInformation = false;
12513 if (A.isAssumedDead(*CB, this, /*LivenessAA=*/nullptr,
12514 UsedAssumedInformation))
12515 return ChangeStatus::UNCHANGED;
12516
12517 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12518 unsigned ProgramAS = CB->getDataLayout().getProgramAddressSpace();
12519 Value *FP = CB->getCalledOperand();
12520 if (FP->getType()->getPointerAddressSpace() != ProgramAS)
12521 FP = new AddrSpaceCastInst(
12522 FP, PointerType::get(FP->getContext(), ProgramAS),
12523 FP->getName() + ".as" + Twine(ProgramAS), CB->getIterator());
12524
12525 bool CBIsVoid = CB->getType()->isVoidTy();
12527 FunctionType *CSFT = CB->getFunctionType();
12528 SmallVector<Value *> CSArgs(CB->args());
12529
12530 // If we know all callees and there are none, the call site is (effectively)
12531 // dead (or UB).
12532 if (AssumedCallees.empty()) {
12533 assert(AllCalleesKnown &&
12534 "Expected all callees to be known if there are none.");
12535 A.changeToUnreachableAfterManifest(CB);
12536 return ChangeStatus::CHANGED;
12537 }
12538
12539 // Special handling for the single callee case.
12540 if (AllCalleesKnown && AssumedCallees.size() == 1) {
12541 auto *NewCallee = AssumedCallees.front();
12542 if (isLegalToPromote(*CB, NewCallee)) {
12543 promoteCall(*CB, NewCallee, nullptr);
12544 NumIndirectCallsPromoted++;
12545 return ChangeStatus::CHANGED;
12546 }
12547 Instruction *NewCall =
12548 CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12549 CB->getName(), CB->getIterator());
12550 if (!CBIsVoid)
12551 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *NewCall);
12552 A.deleteAfterManifest(*CB);
12553 return ChangeStatus::CHANGED;
12554 }
12555
12556 // For each potential value we create a conditional
12557 //
12558 // ```
12559 // if (ptr == value) value(args);
12560 // else ...
12561 // ```
12562 //
12563 bool SpecializedForAnyCallees = false;
12564 bool SpecializedForAllCallees = AllCalleesKnown;
12565 ICmpInst *LastCmp = nullptr;
12566 SmallVector<Function *, 8> SkippedAssumedCallees;
12568 for (Function *NewCallee : AssumedCallees) {
12569 if (!A.shouldSpecializeCallSiteForCallee(*this, *CB, *NewCallee,
12570 AssumedCallees.size())) {
12571 SkippedAssumedCallees.push_back(NewCallee);
12572 SpecializedForAllCallees = false;
12573 continue;
12574 }
12575 SpecializedForAnyCallees = true;
12576
12577 LastCmp = new ICmpInst(IP, llvm::CmpInst::ICMP_EQ, FP, NewCallee);
12578 Instruction *ThenTI =
12579 SplitBlockAndInsertIfThen(LastCmp, IP, /* Unreachable */ false);
12580 BasicBlock *CBBB = CB->getParent();
12581 A.registerManifestAddedBasicBlock(*ThenTI->getParent());
12582 A.registerManifestAddedBasicBlock(*IP->getParent());
12583 auto *SplitTI = cast<CondBrInst>(LastCmp->getNextNode());
12584 BasicBlock *ElseBB;
12585 if (&*IP == CB) {
12586 ElseBB = BasicBlock::Create(ThenTI->getContext(), "",
12587 ThenTI->getFunction(), CBBB);
12588 A.registerManifestAddedBasicBlock(*ElseBB);
12589 IP = UncondBrInst::Create(CBBB, ElseBB)->getIterator();
12590 SplitTI->replaceUsesOfWith(CBBB, ElseBB);
12591 } else {
12592 ElseBB = IP->getParent();
12593 ThenTI->replaceUsesOfWith(ElseBB, CBBB);
12594 }
12595 CastInst *RetBC = nullptr;
12596 CallInst *NewCall = nullptr;
12597 if (isLegalToPromote(*CB, NewCallee)) {
12598 auto *CBClone = cast<CallBase>(CB->clone());
12599 CBClone->insertBefore(ThenTI->getIterator());
12600 NewCall = &cast<CallInst>(promoteCall(*CBClone, NewCallee, &RetBC));
12601 NumIndirectCallsPromoted++;
12602 } else {
12603 NewCall = CallInst::Create(FunctionCallee(CSFT, NewCallee), CSArgs,
12604 CB->getName(), ThenTI->getIterator());
12605 }
12606 NewCalls.push_back({NewCall, RetBC});
12607 }
12608
12609 auto AttachCalleeMetadata = [&](CallBase &IndirectCB) {
12610 if (!AllCalleesKnown)
12611 return ChangeStatus::UNCHANGED;
12612 MDBuilder MDB(IndirectCB.getContext());
12613 MDNode *Callees = MDB.createCallees(SkippedAssumedCallees);
12614 IndirectCB.setMetadata(LLVMContext::MD_callees, Callees);
12615 return ChangeStatus::CHANGED;
12616 };
12617
12618 if (!SpecializedForAnyCallees)
12619 return AttachCalleeMetadata(*CB);
12620
12621 // Check if we need the fallback indirect call still.
12622 if (SpecializedForAllCallees) {
12624 LastCmp->eraseFromParent();
12625 new UnreachableInst(IP->getContext(), IP);
12626 IP->eraseFromParent();
12627 } else {
12628 auto *CBClone = cast<CallInst>(CB->clone());
12629 CBClone->setName(CB->getName());
12630 CBClone->insertBefore(*IP->getParent(), IP);
12631 NewCalls.push_back({CBClone, nullptr});
12632 AttachCalleeMetadata(*CBClone);
12633 }
12634
12635 // Check if we need a PHI to merge the results.
12636 if (!CBIsVoid) {
12637 auto *PHI = PHINode::Create(CB->getType(), NewCalls.size(),
12638 CB->getName() + ".phi",
12639 CB->getParent()->getFirstInsertionPt());
12640 for (auto &It : NewCalls) {
12641 CallBase *NewCall = It.first;
12642 Instruction *CallRet = It.second ? It.second : It.first;
12643 if (CallRet->getType() == CB->getType())
12644 PHI->addIncoming(CallRet, CallRet->getParent());
12645 else if (NewCall->getType()->isVoidTy())
12646 PHI->addIncoming(PoisonValue::get(CB->getType()),
12647 NewCall->getParent());
12648 else
12649 llvm_unreachable("Call return should match or be void!");
12650 }
12651 A.changeAfterManifest(IRPosition::callsite_returned(*CB), *PHI);
12652 }
12653
12654 A.deleteAfterManifest(*CB);
12655 Changed = ChangeStatus::CHANGED;
12656
12657 return Changed;
12658 }
12659
12660 /// See AbstractAttribute::getAsStr().
12661 const std::string getAsStr(Attributor *A) const override {
12662 return std::string(AllCalleesKnown ? "eliminate" : "specialize") +
12663 " indirect call site with " + std::to_string(AssumedCallees.size()) +
12664 " functions";
12665 }
12666
12667 void trackStatistics() const override {
12668 if (AllCalleesKnown) {
12670 Eliminated, CallSites,
12671 "Number of indirect call sites eliminated via specialization")
12672 } else {
12673 STATS_DECLTRACK(Specialized, CallSites,
12674 "Number of indirect call sites specialized")
12675 }
12676 }
12677
12678 bool foreachCallee(function_ref<bool(Function *)> CB) const override {
12679 return isValidState() && AllCalleesKnown && all_of(AssumedCallees, CB);
12680 }
12681
12682private:
12683 /// Map to remember filter results.
12684 DenseMap<Function *, std::optional<bool>> FilterResults;
12685
12686 /// If the !callee metadata was present, this set will contain all potential
12687 /// callees (superset).
12688 SmallSetVector<Function *, 4> PotentialCallees;
12689
12690 /// This set contains all currently assumed calllees, which might grow over
12691 /// time.
12692 SmallSetVector<Function *, 4> AssumedCallees;
12693
12694 /// Flag to indicate if all possible callees are in the AssumedCallees set or
12695 /// if there could be others.
12696 bool AllCalleesKnown = true;
12697};
12698} // namespace
12699
12700/// --------------------- Invariant Load Pointer -------------------------------
12701namespace {
12702
12703struct AAInvariantLoadPointerImpl
12704 : public StateWrapper<BitIntegerState<uint8_t, 15>,
12705 AAInvariantLoadPointer> {
12706
12707 enum {
12708 // pointer does not alias within the bounds of the function
12709 IS_NOALIAS = 1 << 0,
12710 // pointer is not involved in any effectful instructions within the bounds
12711 // of the function
12712 IS_NOEFFECT = 1 << 1,
12713 // loads are invariant within the bounds of the function
12714 IS_LOCALLY_INVARIANT = 1 << 2,
12715 // memory lifetime is constrained within the bounds of the function
12716 IS_LOCALLY_CONSTRAINED = 1 << 3,
12717
12718 IS_BEST_STATE = IS_NOALIAS | IS_NOEFFECT | IS_LOCALLY_INVARIANT |
12719 IS_LOCALLY_CONSTRAINED,
12720 };
12721 static_assert(getBestState() == IS_BEST_STATE, "Unexpected best state");
12722
12723 using Base =
12724 StateWrapper<BitIntegerState<uint8_t, 15>, AAInvariantLoadPointer>;
12725
12726 // the BitIntegerState is optimistic about IS_NOALIAS and IS_NOEFFECT, but
12727 // pessimistic about IS_KNOWN_INVARIANT
12728 AAInvariantLoadPointerImpl(const IRPosition &IRP, Attributor &A)
12729 : Base(IRP) {}
12730
12731 bool isKnownInvariant() const final {
12732 return isKnownLocallyInvariant() && isKnown(IS_LOCALLY_CONSTRAINED);
12733 }
12734
12735 bool isKnownLocallyInvariant() const final {
12736 if (isKnown(IS_LOCALLY_INVARIANT))
12737 return true;
12738 return isKnown(IS_NOALIAS | IS_NOEFFECT);
12739 }
12740
12741 bool isAssumedInvariant() const final {
12742 return isAssumedLocallyInvariant() && isAssumed(IS_LOCALLY_CONSTRAINED);
12743 }
12744
12745 bool isAssumedLocallyInvariant() const final {
12746 if (isAssumed(IS_LOCALLY_INVARIANT))
12747 return true;
12748 return isAssumed(IS_NOALIAS | IS_NOEFFECT);
12749 }
12750
12751 ChangeStatus updateImpl(Attributor &A) override {
12752 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12753
12754 Changed |= updateNoAlias(A);
12755 if (requiresNoAlias() && !isAssumed(IS_NOALIAS))
12756 return indicatePessimisticFixpoint();
12757
12758 Changed |= updateNoEffect(A);
12759
12760 Changed |= updateLocalInvariance(A);
12761
12762 return Changed;
12763 }
12764
12765 ChangeStatus manifest(Attributor &A) override {
12766 if (!isKnownInvariant())
12767 return ChangeStatus::UNCHANGED;
12768
12769 ChangeStatus Changed = ChangeStatus::UNCHANGED;
12770 const Value *Ptr = &getAssociatedValue();
12771 const auto TagInvariantLoads = [&](const Use &U, bool &) {
12772 if (U.get() != Ptr)
12773 return true;
12774 auto *I = dyn_cast<Instruction>(U.getUser());
12775 if (!I)
12776 return true;
12777
12778 // Ensure that we are only changing uses from the corresponding callgraph
12779 // SSC in the case that the AA isn't run on the entire module
12780 if (!A.isRunOn(I->getFunction()))
12781 return true;
12782
12783 if (I->hasMetadata(LLVMContext::MD_invariant_load))
12784 return true;
12785
12786 if (auto *LI = dyn_cast<LoadInst>(I)) {
12787 LI->setMetadata(LLVMContext::MD_invariant_load,
12788 MDNode::get(LI->getContext(), {}));
12789 Changed = ChangeStatus::CHANGED;
12790 }
12791 return true;
12792 };
12793
12794 (void)A.checkForAllUses(TagInvariantLoads, *this, *Ptr);
12795 return Changed;
12796 }
12797
12798 /// See AbstractAttribute::getAsStr().
12799 const std::string getAsStr(Attributor *) const override {
12800 if (isKnownInvariant())
12801 return "load-invariant pointer";
12802 return "non-invariant pointer";
12803 }
12804
12805 /// See AbstractAttribute::trackStatistics().
12806 void trackStatistics() const override {}
12807
12808private:
12809 /// Indicate that noalias is required for the pointer to be invariant.
12810 bool requiresNoAlias() const {
12811 switch (getPositionKind()) {
12812 default:
12813 // Conservatively default to require noalias.
12814 return true;
12815 case IRP_FLOAT:
12816 case IRP_RETURNED:
12817 case IRP_CALL_SITE:
12818 return false;
12819 case IRP_CALL_SITE_RETURNED: {
12820 const auto &CB = cast<CallBase>(getAnchorValue());
12822 &CB, /*MustPreserveOffset=*/false);
12823 }
12824 case IRP_ARGUMENT: {
12825 const Function *F = getAssociatedFunction();
12826 assert(F && "no associated function for argument");
12827 return !isCallableCC(F->getCallingConv());
12828 }
12829 }
12830 }
12831
12832 bool isExternal() const {
12833 const Function *F = getAssociatedFunction();
12834 if (!F)
12835 return true;
12836 return isCallableCC(F->getCallingConv()) &&
12837 getPositionKind() != IRP_CALL_SITE_RETURNED;
12838 }
12839
12840 ChangeStatus updateNoAlias(Attributor &A) {
12841 if (isKnown(IS_NOALIAS) || !isAssumed(IS_NOALIAS))
12842 return ChangeStatus::UNCHANGED;
12843
12844 // Try to use AANoAlias.
12845 if (const auto *ANoAlias = A.getOrCreateAAFor<AANoAlias>(
12846 getIRPosition(), this, DepClassTy::REQUIRED)) {
12847 if (ANoAlias->isKnownNoAlias()) {
12848 addKnownBits(IS_NOALIAS);
12849 return ChangeStatus::CHANGED;
12850 }
12851
12852 if (!ANoAlias->isAssumedNoAlias()) {
12853 removeAssumedBits(IS_NOALIAS);
12854 return ChangeStatus::CHANGED;
12855 }
12856
12857 return ChangeStatus::UNCHANGED;
12858 }
12859
12860 // Try to infer noalias from argument attribute, since it is applicable for
12861 // the duration of the function.
12862 if (const Argument *Arg = getAssociatedArgument()) {
12863 if (Arg->hasNoAliasAttr()) {
12864 addKnownBits(IS_NOALIAS);
12865 return ChangeStatus::UNCHANGED;
12866 }
12867
12868 // Noalias information is not provided, and cannot be inferred,
12869 // so we conservatively assume the pointer aliases.
12870 removeAssumedBits(IS_NOALIAS);
12871 return ChangeStatus::CHANGED;
12872 }
12873
12874 return ChangeStatus::UNCHANGED;
12875 }
12876
12877 ChangeStatus updateNoEffect(Attributor &A) {
12878 if (isKnown(IS_NOEFFECT) || !isAssumed(IS_NOEFFECT))
12879 return ChangeStatus::UNCHANGED;
12880
12881 if (!getAssociatedFunction())
12882 return indicatePessimisticFixpoint();
12883
12884 if (isa<AllocaInst>(&getAssociatedValue()))
12885 return indicatePessimisticFixpoint();
12886
12887 const auto HasNoEffectLoads = [&](const Use &U, bool &) {
12888 const auto *LI = dyn_cast<LoadInst>(U.getUser());
12889 return !LI || !LI->mayHaveSideEffects();
12890 };
12891 if (!A.checkForAllUses(HasNoEffectLoads, *this, getAssociatedValue()))
12892 return indicatePessimisticFixpoint();
12893
12894 if (const auto *AMemoryBehavior = A.getOrCreateAAFor<AAMemoryBehavior>(
12895 getIRPosition(), this, DepClassTy::REQUIRED)) {
12896 // For non-instructions, try to use AAMemoryBehavior to infer the readonly
12897 // attribute
12898 if (!AMemoryBehavior->isAssumedReadOnly())
12899 return indicatePessimisticFixpoint();
12900
12901 if (AMemoryBehavior->isKnownReadOnly()) {
12902 addKnownBits(IS_NOEFFECT);
12903 return ChangeStatus::UNCHANGED;
12904 }
12905
12906 return ChangeStatus::UNCHANGED;
12907 }
12908
12909 if (const Argument *Arg = getAssociatedArgument()) {
12910 if (Arg->onlyReadsMemory()) {
12911 addKnownBits(IS_NOEFFECT);
12912 return ChangeStatus::UNCHANGED;
12913 }
12914
12915 // Readonly information is not provided, and cannot be inferred from
12916 // AAMemoryBehavior.
12917 return indicatePessimisticFixpoint();
12918 }
12919
12920 return ChangeStatus::UNCHANGED;
12921 }
12922
12923 ChangeStatus updateLocalInvariance(Attributor &A) {
12924 if (isKnown(IS_LOCALLY_INVARIANT) || !isAssumed(IS_LOCALLY_INVARIANT))
12925 return ChangeStatus::UNCHANGED;
12926
12927 // try to infer invariance from underlying objects
12928 const auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
12929 getIRPosition(), this, DepClassTy::REQUIRED);
12930 if (!AUO)
12931 return ChangeStatus::UNCHANGED;
12932
12933 bool UsedAssumedInformation = false;
12934 const auto IsLocallyInvariantLoadIfPointer = [&](const Value &V) {
12935 if (!V.getType()->isPointerTy())
12936 return true;
12937 const auto *IsInvariantLoadPointer =
12938 A.getOrCreateAAFor<AAInvariantLoadPointer>(IRPosition::value(V), this,
12939 DepClassTy::REQUIRED);
12940 // Conservatively fail if invariance cannot be inferred.
12941 if (!IsInvariantLoadPointer)
12942 return false;
12943
12944 if (IsInvariantLoadPointer->isKnownLocallyInvariant())
12945 return true;
12946 if (!IsInvariantLoadPointer->isAssumedLocallyInvariant())
12947 return false;
12948
12949 UsedAssumedInformation = true;
12950 return true;
12951 };
12952 if (!AUO->forallUnderlyingObjects(IsLocallyInvariantLoadIfPointer))
12953 return indicatePessimisticFixpoint();
12954
12955 if (const auto *CB = dyn_cast<CallBase>(&getAnchorValue())) {
12957 CB, /*MustPreserveOffset=*/false)) {
12958 for (const Value *Arg : CB->args()) {
12959 if (!IsLocallyInvariantLoadIfPointer(*Arg))
12960 return indicatePessimisticFixpoint();
12961 }
12962 }
12963 }
12964
12965 if (!UsedAssumedInformation) {
12966 // Pointer is known and not just assumed to be locally invariant.
12967 addKnownBits(IS_LOCALLY_INVARIANT);
12968 return ChangeStatus::CHANGED;
12969 }
12970
12971 return ChangeStatus::UNCHANGED;
12972 }
12973};
12974
12975struct AAInvariantLoadPointerFloating final : AAInvariantLoadPointerImpl {
12976 AAInvariantLoadPointerFloating(const IRPosition &IRP, Attributor &A)
12977 : AAInvariantLoadPointerImpl(IRP, A) {}
12978};
12979
12980struct AAInvariantLoadPointerReturned final : AAInvariantLoadPointerImpl {
12981 AAInvariantLoadPointerReturned(const IRPosition &IRP, Attributor &A)
12982 : AAInvariantLoadPointerImpl(IRP, A) {}
12983
12984 void initialize(Attributor &) override {
12985 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
12986 }
12987};
12988
12989struct AAInvariantLoadPointerCallSiteReturned final
12990 : AAInvariantLoadPointerImpl {
12991 AAInvariantLoadPointerCallSiteReturned(const IRPosition &IRP, Attributor &A)
12992 : AAInvariantLoadPointerImpl(IRP, A) {}
12993
12994 void initialize(Attributor &A) override {
12995 const Function *F = getAssociatedFunction();
12996 assert(F && "no associated function for return from call");
12997
12998 if (!F->isDeclaration() && !F->isIntrinsic())
12999 return AAInvariantLoadPointerImpl::initialize(A);
13000
13001 const auto &CB = cast<CallBase>(getAnchorValue());
13003 &CB, /*MustPreserveOffset=*/false))
13004 return AAInvariantLoadPointerImpl::initialize(A);
13005
13006 if (F->onlyReadsMemory() && F->hasNoSync())
13007 return AAInvariantLoadPointerImpl::initialize(A);
13008
13009 // At this point, the function is opaque, so we conservatively assume
13010 // non-invariance.
13011 indicatePessimisticFixpoint();
13012 }
13013};
13014
13015struct AAInvariantLoadPointerArgument final : AAInvariantLoadPointerImpl {
13016 AAInvariantLoadPointerArgument(const IRPosition &IRP, Attributor &A)
13017 : AAInvariantLoadPointerImpl(IRP, A) {}
13018
13019 void initialize(Attributor &) override {
13020 const Function *F = getAssociatedFunction();
13021 assert(F && "no associated function for argument");
13022
13023 if (!isCallableCC(F->getCallingConv())) {
13024 addKnownBits(IS_LOCALLY_CONSTRAINED);
13025 return;
13026 }
13027
13028 if (!F->hasLocalLinkage())
13029 removeAssumedBits(IS_LOCALLY_CONSTRAINED);
13030 }
13031};
13032
13033struct AAInvariantLoadPointerCallSiteArgument final
13034 : AAInvariantLoadPointerImpl {
13035 AAInvariantLoadPointerCallSiteArgument(const IRPosition &IRP, Attributor &A)
13036 : AAInvariantLoadPointerImpl(IRP, A) {}
13037};
13038} // namespace
13039
13040/// ------------------------ Address Space ------------------------------------
13041namespace {
13042
13043template <typename InstType>
13044static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
13045 Value *OriginalValue, PointerType *NewPtrTy,
13046 bool UseOriginalValue) {
13047 if (U.getOperandNo() != InstType::getPointerOperandIndex())
13048 return false;
13049
13050 if (MemInst->isVolatile()) {
13051 auto *TTI = A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(
13052 *MemInst->getFunction());
13053 unsigned NewAS = NewPtrTy->getPointerAddressSpace();
13054 if (!TTI || !TTI->hasVolatileVariant(MemInst, NewAS))
13055 return false;
13056 }
13057
13058 if (UseOriginalValue) {
13059 A.changeUseAfterManifest(const_cast<Use &>(U), *OriginalValue);
13060 return true;
13061 }
13062
13063 Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
13064 CastInst->insertBefore(MemInst->getIterator());
13065 A.changeUseAfterManifest(const_cast<Use &>(U), *CastInst);
13066 return true;
13067}
13068
13069struct AAAddressSpaceImpl : public AAAddressSpace {
13070 AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
13071 : AAAddressSpace(IRP, A) {}
13072
13073 uint32_t getAddressSpace() const override {
13074 assert(isValidState() && "the AA is invalid");
13075 return AssumedAddressSpace;
13076 }
13077
13078 /// See AbstractAttribute::initialize(...).
13079 void initialize(Attributor &A) override {
13080 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13081 "Associated value is not a pointer");
13082
13083 if (!A.getInfoCache().getFlatAddressSpace().has_value()) {
13084 indicatePessimisticFixpoint();
13085 return;
13086 }
13087
13088 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13089 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13090 if (AS != FlatAS) {
13091 [[maybe_unused]] bool R = takeAddressSpace(AS);
13092 assert(R && "The take should happen");
13093 indicateOptimisticFixpoint();
13094 }
13095 }
13096
13097 ChangeStatus updateImpl(Attributor &A) override {
13098 uint32_t OldAddressSpace = AssumedAddressSpace;
13099 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13100
13101 auto CheckAddressSpace = [&](Value &Obj) {
13102 // Ignore undef.
13103 if (isa<UndefValue>(&Obj))
13104 return true;
13105
13106 // If the object already has a non-flat address space, we simply take it.
13107 unsigned ObjAS = Obj.getType()->getPointerAddressSpace();
13108 if (ObjAS != FlatAS)
13109 return takeAddressSpace(ObjAS);
13110
13111 // At this point, we know Obj is in the flat address space. For a final
13112 // attempt, we want to use getAssumedAddrSpace, but first we must get the
13113 // associated function, if possible.
13114 Function *F = nullptr;
13115 if (auto *Arg = dyn_cast<Argument>(&Obj))
13116 F = Arg->getParent();
13117 else if (auto *I = dyn_cast<Instruction>(&Obj))
13118 F = I->getFunction();
13119
13120 // Use getAssumedAddrSpace if the associated function exists.
13121 if (F) {
13122 auto *TTI =
13123 A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(*F);
13124 unsigned AssumedAS = TTI->getAssumedAddrSpace(&Obj);
13125 if (AssumedAS != ~0U)
13126 return takeAddressSpace(AssumedAS);
13127 }
13128
13129 // Now we can't do anything else but to take the flat AS.
13130 return takeAddressSpace(FlatAS);
13131 };
13132
13133 auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
13134 DepClassTy::REQUIRED);
13135 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13136 return indicatePessimisticFixpoint();
13137
13138 return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
13139 : ChangeStatus::CHANGED;
13140 }
13141
13142 /// See AbstractAttribute::manifest(...).
13143 ChangeStatus manifest(Attributor &A) override {
13144 unsigned NewAS = getAddressSpace();
13145
13146 if (NewAS == InvalidAddressSpace ||
13147 NewAS == getAssociatedType()->getPointerAddressSpace())
13148 return ChangeStatus::UNCHANGED;
13149
13150 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13151
13152 Value *AssociatedValue = &getAssociatedValue();
13153 Value *OriginalValue = peelAddrspacecast(AssociatedValue, FlatAS);
13154
13155 PointerType *NewPtrTy =
13156 PointerType::get(getAssociatedType()->getContext(), NewAS);
13157 bool UseOriginalValue =
13158 OriginalValue->getType()->getPointerAddressSpace() == NewAS;
13159
13160 bool Changed = false;
13161
13162 auto Pred = [&](const Use &U, bool &) {
13163 if (U.get() != AssociatedValue)
13164 return true;
13165 auto *Inst = dyn_cast<Instruction>(U.getUser());
13166 if (!Inst)
13167 return true;
13168 // This is a WA to make sure we only change uses from the corresponding
13169 // CGSCC if the AA is run on CGSCC instead of the entire module.
13170 if (!A.isRunOn(Inst->getFunction()))
13171 return true;
13172 if (auto *LI = dyn_cast<LoadInst>(Inst)) {
13173 Changed |=
13174 makeChange(A, LI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13175 } else if (auto *SI = dyn_cast<StoreInst>(Inst)) {
13176 Changed |=
13177 makeChange(A, SI, U, OriginalValue, NewPtrTy, UseOriginalValue);
13178 } else if (auto *RMW = dyn_cast<AtomicRMWInst>(Inst)) {
13179 Changed |=
13180 makeChange(A, RMW, U, OriginalValue, NewPtrTy, UseOriginalValue);
13181 } else if (auto *CmpX = dyn_cast<AtomicCmpXchgInst>(Inst)) {
13182 Changed |=
13183 makeChange(A, CmpX, U, OriginalValue, NewPtrTy, UseOriginalValue);
13184 }
13185 return true;
13186 };
13187
13188 // It doesn't matter if we can't check all uses as we can simply
13189 // conservatively ignore those that can not be visited.
13190 (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
13191 /* CheckBBLivenessOnly */ true);
13192
13193 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13194 }
13195
13196 /// See AbstractAttribute::getAsStr().
13197 const std::string getAsStr(Attributor *A) const override {
13198 if (!isValidState())
13199 return "addrspace(<invalid>)";
13200 return "addrspace(" +
13201 (AssumedAddressSpace == InvalidAddressSpace
13202 ? "none"
13203 : std::to_string(AssumedAddressSpace)) +
13204 ")";
13205 }
13206
13207private:
13208 uint32_t AssumedAddressSpace = InvalidAddressSpace;
13209
13210 bool takeAddressSpace(uint32_t AS) {
13211 if (AssumedAddressSpace == InvalidAddressSpace) {
13212 AssumedAddressSpace = AS;
13213 return true;
13214 }
13215 return AssumedAddressSpace == AS;
13216 }
13217
13218 static Value *peelAddrspacecast(Value *V, unsigned FlatAS) {
13219 if (auto *I = dyn_cast<AddrSpaceCastInst>(V)) {
13220 assert(I->getSrcAddressSpace() != FlatAS &&
13221 "there should not be flat AS -> non-flat AS");
13222 return I->getPointerOperand();
13223 }
13224 if (auto *C = dyn_cast<ConstantExpr>(V))
13225 if (C->getOpcode() == Instruction::AddrSpaceCast) {
13226 assert(C->getOperand(0)->getType()->getPointerAddressSpace() !=
13227 FlatAS &&
13228 "there should not be flat AS -> non-flat AS X");
13229 return C->getOperand(0);
13230 }
13231 return V;
13232 }
13233};
13234
13235struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
13236 AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
13237 : AAAddressSpaceImpl(IRP, A) {}
13238
13239 void trackStatistics() const override {
13241 }
13242};
13243
13244struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
13245 AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
13246 : AAAddressSpaceImpl(IRP, A) {}
13247
13248 /// See AbstractAttribute::initialize(...).
13249 void initialize(Attributor &A) override {
13250 // TODO: we don't rewrite function argument for now because it will need to
13251 // rewrite the function signature and all call sites.
13252 (void)indicatePessimisticFixpoint();
13253 }
13254
13255 void trackStatistics() const override {
13256 STATS_DECLTRACK_FNRET_ATTR(addrspace);
13257 }
13258};
13259
13260struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
13261 AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13262 : AAAddressSpaceImpl(IRP, A) {}
13263
13264 void trackStatistics() const override {
13265 STATS_DECLTRACK_CSRET_ATTR(addrspace);
13266 }
13267};
13268
13269struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
13270 AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
13271 : AAAddressSpaceImpl(IRP, A) {}
13272
13273 void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
13274};
13275
13276struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
13277 AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13278 : AAAddressSpaceImpl(IRP, A) {}
13279
13280 /// See AbstractAttribute::initialize(...).
13281 void initialize(Attributor &A) override {
13282 // TODO: we don't rewrite call site argument for now because it will need to
13283 // rewrite the function signature of the callee.
13284 (void)indicatePessimisticFixpoint();
13285 }
13286
13287 void trackStatistics() const override {
13288 STATS_DECLTRACK_CSARG_ATTR(addrspace);
13289 }
13290};
13291} // namespace
13292
13293/// ------------------------ No Alias Address Space ---------------------------
13294// This attribute assumes flat address space can alias all other address space
13295
13296// TODO: this is similar to AAAddressSpace, most of the code should be merged.
13297// But merging it created failing cased on gateway test that cannot be
13298// reproduced locally. So should open a separated PR to handle the merge of
13299// AANoAliasAddrSpace and AAAddressSpace attribute
13300
13301namespace {
13302struct AANoAliasAddrSpaceImpl : public AANoAliasAddrSpace {
13303 AANoAliasAddrSpaceImpl(const IRPosition &IRP, Attributor &A)
13304 : AANoAliasAddrSpace(IRP, A) {}
13305
13306 void initialize(Attributor &A) override {
13307 assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
13308 "Associated value is not a pointer");
13309
13310 resetASRanges(A);
13311
13312 std::optional<unsigned> FlatAS = A.getInfoCache().getFlatAddressSpace();
13313 if (!FlatAS.has_value()) {
13314 indicatePessimisticFixpoint();
13315 return;
13316 }
13317
13318 removeAS(*FlatAS);
13319
13320 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13321 if (AS != *FlatAS) {
13322 removeAS(AS);
13323 indicateOptimisticFixpoint();
13324 }
13325 }
13326
13327 ChangeStatus updateImpl(Attributor &A) override {
13328 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13329 uint32_t OldAssumed = getAssumed();
13330
13331 auto CheckAddressSpace = [&](Value &Obj) {
13332 if (isa<PoisonValue>(&Obj))
13333 return true;
13334
13335 unsigned AS = Obj.getType()->getPointerAddressSpace();
13336 if (AS == FlatAS)
13337 return false;
13338
13339 removeAS(Obj.getType()->getPointerAddressSpace());
13340 return true;
13341 };
13342
13343 const AAUnderlyingObjects *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(
13344 getIRPosition(), this, DepClassTy::REQUIRED);
13345 if (!AUO->forallUnderlyingObjects(CheckAddressSpace))
13346 return indicatePessimisticFixpoint();
13347
13348 return OldAssumed == getAssumed() ? ChangeStatus::UNCHANGED
13349 : ChangeStatus::CHANGED;
13350 }
13351
13352 /// See AbstractAttribute::manifest(...).
13353 ChangeStatus manifest(Attributor &A) override {
13354 unsigned FlatAS = A.getInfoCache().getFlatAddressSpace().value();
13355
13356 unsigned AS = getAssociatedType()->getPointerAddressSpace();
13357 if (AS != FlatAS || Map.empty())
13358 return ChangeStatus::UNCHANGED;
13359
13360 LLVMContext &Ctx = getAssociatedValue().getContext();
13361 MDNode *NoAliasASNode = nullptr;
13362 MDBuilder MDB(Ctx);
13363 // Has to use iterator to get the range info.
13364 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13365 if (!I.value())
13366 continue;
13367 unsigned Upper = I.stop();
13368 unsigned Lower = I.start();
13369 if (!NoAliasASNode) {
13370 NoAliasASNode = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13371 continue;
13372 }
13373 MDNode *ASRange = MDB.createRange(APInt(32, Lower), APInt(32, Upper + 1));
13374 NoAliasASNode = MDNode::getMostGenericRange(NoAliasASNode, ASRange);
13375 }
13376
13377 Value *AssociatedValue = &getAssociatedValue();
13378 bool Changed = false;
13379
13380 auto AddNoAliasAttr = [&](const Use &U, bool &) {
13381 if (U.get() != AssociatedValue)
13382 return true;
13383 Instruction *Inst = dyn_cast<Instruction>(U.getUser());
13384 if (!Inst || Inst->hasMetadata(LLVMContext::MD_noalias_addrspace))
13385 return true;
13386 if (!isa<LoadInst>(Inst) && !isa<StoreInst>(Inst) &&
13388 return true;
13389 if (!A.isRunOn(Inst->getFunction()))
13390 return true;
13391 Inst->setMetadata(LLVMContext::MD_noalias_addrspace, NoAliasASNode);
13392 Changed = true;
13393 return true;
13394 };
13395 (void)A.checkForAllUses(AddNoAliasAttr, *this, *AssociatedValue,
13396 /*CheckBBLivenessOnly=*/true);
13397 return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
13398 }
13399
13400 /// See AbstractAttribute::getAsStr().
13401 const std::string getAsStr(Attributor *A) const override {
13402 if (!isValidState())
13403 return "<invalid>";
13404 std::string Str;
13405 raw_string_ostream OS(Str);
13406 OS << "CanNotBeAddrSpace(";
13407 for (RangeMap::const_iterator I = Map.begin(); I != Map.end(); I++) {
13408 unsigned Upper = I.stop();
13409 unsigned Lower = I.start();
13410 OS << ' ' << '[' << Upper << ',' << Lower + 1 << ')';
13411 }
13412 OS << " )";
13413 return OS.str();
13414 }
13415
13416private:
13417 void removeAS(unsigned AS) {
13418 RangeMap::iterator I = Map.find(AS);
13419
13420 if (I != Map.end()) {
13421 unsigned Upper = I.stop();
13422 unsigned Lower = I.start();
13423 I.erase();
13424 if (Upper == Lower)
13425 return;
13426 if (AS != ~((unsigned)0) && AS + 1 <= Upper)
13427 Map.insert(AS + 1, Upper, /*what ever this variable name is=*/true);
13428 if (AS != 0 && Lower <= AS - 1)
13429 Map.insert(Lower, AS - 1, true);
13430 }
13431 }
13432
13433 void resetASRanges(Attributor &A) {
13434 Map.clear();
13435 Map.insert(0, A.getInfoCache().getMaxAddrSpace(), true);
13436 }
13437};
13438
13439struct AANoAliasAddrSpaceFloating final : AANoAliasAddrSpaceImpl {
13440 AANoAliasAddrSpaceFloating(const IRPosition &IRP, Attributor &A)
13441 : AANoAliasAddrSpaceImpl(IRP, A) {}
13442
13443 void trackStatistics() const override {
13444 STATS_DECLTRACK_FLOATING_ATTR(noaliasaddrspace);
13445 }
13446};
13447
13448struct AANoAliasAddrSpaceReturned final : AANoAliasAddrSpaceImpl {
13449 AANoAliasAddrSpaceReturned(const IRPosition &IRP, Attributor &A)
13450 : AANoAliasAddrSpaceImpl(IRP, A) {}
13451
13452 void trackStatistics() const override {
13453 STATS_DECLTRACK_FNRET_ATTR(noaliasaddrspace);
13454 }
13455};
13456
13457struct AANoAliasAddrSpaceCallSiteReturned final : AANoAliasAddrSpaceImpl {
13458 AANoAliasAddrSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
13459 : AANoAliasAddrSpaceImpl(IRP, A) {}
13460
13461 void trackStatistics() const override {
13462 STATS_DECLTRACK_CSRET_ATTR(noaliasaddrspace);
13463 }
13464};
13465
13466struct AANoAliasAddrSpaceArgument final : AANoAliasAddrSpaceImpl {
13467 AANoAliasAddrSpaceArgument(const IRPosition &IRP, Attributor &A)
13468 : AANoAliasAddrSpaceImpl(IRP, A) {}
13469
13470 void trackStatistics() const override {
13471 STATS_DECLTRACK_ARG_ATTR(noaliasaddrspace);
13472 }
13473};
13474
13475struct AANoAliasAddrSpaceCallSiteArgument final : AANoAliasAddrSpaceImpl {
13476 AANoAliasAddrSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
13477 : AANoAliasAddrSpaceImpl(IRP, A) {}
13478
13479 void trackStatistics() const override {
13480 STATS_DECLTRACK_CSARG_ATTR(noaliasaddrspace);
13481 }
13482};
13483} // namespace
13484/// ----------- Allocation Info ----------
13485namespace {
13486struct AAAllocationInfoImpl : public AAAllocationInfo {
13487 AAAllocationInfoImpl(const IRPosition &IRP, Attributor &A)
13488 : AAAllocationInfo(IRP, A) {}
13489
13490 std::optional<TypeSize> getAllocatedSize() const override {
13491 assert(isValidState() && "the AA is invalid");
13492 return AssumedAllocatedSize;
13493 }
13494
13495 std::optional<TypeSize> findInitialAllocationSize(Instruction *I,
13496 const DataLayout &DL) {
13497
13498 // TODO: implement case for malloc like instructions
13499 switch (I->getOpcode()) {
13500 case Instruction::Alloca: {
13501 AllocaInst *AI = cast<AllocaInst>(I);
13502 return AI->getAllocationSize(DL);
13503 }
13504 default:
13505 return std::nullopt;
13506 }
13507 }
13508
13509 ChangeStatus updateImpl(Attributor &A) override {
13510
13511 const IRPosition &IRP = getIRPosition();
13512 Instruction *I = IRP.getCtxI();
13513
13514 // TODO: update check for malloc like calls
13515 if (!isa<AllocaInst>(I))
13516 return indicatePessimisticFixpoint();
13517
13518 bool IsKnownNoCapture;
13520 A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture))
13521 return indicatePessimisticFixpoint();
13522
13523 const AAPointerInfo *PI =
13524 A.getOrCreateAAFor<AAPointerInfo>(IRP, *this, DepClassTy::REQUIRED);
13525
13526 if (!PI)
13527 return indicatePessimisticFixpoint();
13528
13529 if (!PI->getState().isValidState() || PI->reachesReturn())
13530 return indicatePessimisticFixpoint();
13531
13532 const DataLayout &DL = A.getDataLayout();
13533 const auto AllocationSize = findInitialAllocationSize(I, DL);
13534
13535 // If allocation size is nullopt, we give up.
13536 if (!AllocationSize)
13537 return indicatePessimisticFixpoint();
13538
13539 // For zero sized allocations, we give up.
13540 // Since we can't reduce further
13541 if (*AllocationSize == 0)
13542 return indicatePessimisticFixpoint();
13543
13544 int64_t BinSize = PI->numOffsetBins();
13545
13546 // TODO: implement for multiple bins
13547 if (BinSize > 1)
13548 return indicatePessimisticFixpoint();
13549
13550 if (BinSize == 0) {
13551 auto NewAllocationSize = std::make_optional<TypeSize>(0, false);
13552 if (!changeAllocationSize(NewAllocationSize))
13553 return ChangeStatus::UNCHANGED;
13554 return ChangeStatus::CHANGED;
13555 }
13556
13557 // TODO: refactor this to be part of multiple bin case
13558 const auto &It = PI->begin();
13559
13560 // TODO: handle if Offset is not zero
13561 if (It->first.Offset != 0)
13562 return indicatePessimisticFixpoint();
13563
13564 uint64_t SizeOfBin = It->first.Offset + It->first.Size;
13565
13566 if (SizeOfBin >= *AllocationSize)
13567 return indicatePessimisticFixpoint();
13568
13569 auto NewAllocationSize = std::make_optional<TypeSize>(SizeOfBin * 8, false);
13570
13571 if (!changeAllocationSize(NewAllocationSize))
13572 return ChangeStatus::UNCHANGED;
13573
13574 return ChangeStatus::CHANGED;
13575 }
13576
13577 /// See AbstractAttribute::manifest(...).
13578 ChangeStatus manifest(Attributor &A) override {
13579
13580 assert(isValidState() &&
13581 "Manifest should only be called if the state is valid.");
13582
13583 Instruction *I = getIRPosition().getCtxI();
13584
13585 auto FixedAllocatedSizeInBits = getAllocatedSize()->getFixedValue();
13586
13587 unsigned long NumBytesToAllocate = (FixedAllocatedSizeInBits + 7) / 8;
13588
13589 switch (I->getOpcode()) {
13590 // TODO: add case for malloc like calls
13591 case Instruction::Alloca: {
13592
13593 AllocaInst *AI = cast<AllocaInst>(I);
13594
13595 Type *CharType = Type::getInt8Ty(I->getContext());
13596
13597 auto *NumBytesToValue =
13598 ConstantInt::get(I->getContext(), APInt(32, NumBytesToAllocate));
13599
13600 BasicBlock::iterator insertPt = AI->getIterator();
13601 insertPt = std::next(insertPt);
13602 AllocaInst *NewAllocaInst =
13603 new AllocaInst(CharType, AI->getAddressSpace(), NumBytesToValue,
13604 AI->getAlign(), AI->getName(), insertPt);
13605
13606 if (A.changeAfterManifest(IRPosition::inst(*AI), *NewAllocaInst))
13607 return ChangeStatus::CHANGED;
13608
13609 break;
13610 }
13611 default:
13612 break;
13613 }
13614
13615 return ChangeStatus::UNCHANGED;
13616 }
13617
13618 /// See AbstractAttribute::getAsStr().
13619 const std::string getAsStr(Attributor *A) const override {
13620 if (!isValidState())
13621 return "allocationinfo(<invalid>)";
13622 return "allocationinfo(" +
13623 (AssumedAllocatedSize == HasNoAllocationSize
13624 ? "none"
13625 : std::to_string(AssumedAllocatedSize->getFixedValue())) +
13626 ")";
13627 }
13628
13629private:
13630 std::optional<TypeSize> AssumedAllocatedSize = HasNoAllocationSize;
13631
13632 // Maintain the computed allocation size of the object.
13633 // Returns (bool) weather the size of the allocation was modified or not.
13634 bool changeAllocationSize(std::optional<TypeSize> Size) {
13635 if (AssumedAllocatedSize == HasNoAllocationSize ||
13636 AssumedAllocatedSize != Size) {
13637 AssumedAllocatedSize = Size;
13638 return true;
13639 }
13640 return false;
13641 }
13642};
13643
13644struct AAAllocationInfoFloating : AAAllocationInfoImpl {
13645 AAAllocationInfoFloating(const IRPosition &IRP, Attributor &A)
13646 : AAAllocationInfoImpl(IRP, A) {}
13647
13648 void trackStatistics() const override {
13649 STATS_DECLTRACK_FLOATING_ATTR(allocationinfo);
13650 }
13651};
13652
13653struct AAAllocationInfoReturned : AAAllocationInfoImpl {
13654 AAAllocationInfoReturned(const IRPosition &IRP, Attributor &A)
13655 : AAAllocationInfoImpl(IRP, A) {}
13656
13657 /// See AbstractAttribute::initialize(...).
13658 void initialize(Attributor &A) override {
13659 // TODO: we don't rewrite function argument for now because it will need to
13660 // rewrite the function signature and all call sites
13661 (void)indicatePessimisticFixpoint();
13662 }
13663
13664 void trackStatistics() const override {
13665 STATS_DECLTRACK_FNRET_ATTR(allocationinfo);
13666 }
13667};
13668
13669struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {
13670 AAAllocationInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
13671 : AAAllocationInfoImpl(IRP, A) {}
13672
13673 void trackStatistics() const override {
13674 STATS_DECLTRACK_CSRET_ATTR(allocationinfo);
13675 }
13676};
13677
13678struct AAAllocationInfoArgument : AAAllocationInfoImpl {
13679 AAAllocationInfoArgument(const IRPosition &IRP, Attributor &A)
13680 : AAAllocationInfoImpl(IRP, A) {}
13681
13682 void trackStatistics() const override {
13683 STATS_DECLTRACK_ARG_ATTR(allocationinfo);
13684 }
13685};
13686
13687struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {
13688 AAAllocationInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
13689 : AAAllocationInfoImpl(IRP, A) {}
13690
13691 /// See AbstractAttribute::initialize(...).
13692 void initialize(Attributor &A) override {
13693
13694 (void)indicatePessimisticFixpoint();
13695 }
13696
13697 void trackStatistics() const override {
13698 STATS_DECLTRACK_CSARG_ATTR(allocationinfo);
13699 }
13700};
13701} // namespace
13702
13703const char AANoUnwind::ID = 0;
13704const char AANoSync::ID = 0;
13705const char AANoFree::ID = 0;
13706const char AANonNull::ID = 0;
13707const char AAMustProgress::ID = 0;
13708const char AANoRecurse::ID = 0;
13709const char AANonConvergent::ID = 0;
13710const char AAWillReturn::ID = 0;
13711const char AAUndefinedBehavior::ID = 0;
13712const char AANoAlias::ID = 0;
13713const char AAIntraFnReachability::ID = 0;
13714const char AANoReturn::ID = 0;
13715const char AAIsDead::ID = 0;
13716const char AADereferenceable::ID = 0;
13717const char AAAlign::ID = 0;
13718const char AAInstanceInfo::ID = 0;
13719const char AANoCapture::ID = 0;
13720const char AAValueSimplify::ID = 0;
13721const char AAHeapToStack::ID = 0;
13722const char AAPrivatizablePtr::ID = 0;
13723const char AAMemoryBehavior::ID = 0;
13724const char AAMemoryLocation::ID = 0;
13725const char AAValueConstantRange::ID = 0;
13726const char AAPotentialConstantValues::ID = 0;
13727const char AAPotentialValues::ID = 0;
13728const char AANoUndef::ID = 0;
13729const char AANoFPClass::ID = 0;
13730const char AACallEdges::ID = 0;
13731const char AAInterFnReachability::ID = 0;
13732const char AAPointerInfo::ID = 0;
13733const char AAAssumptionInfo::ID = 0;
13734const char AAUnderlyingObjects::ID = 0;
13735const char AAInvariantLoadPointer::ID = 0;
13736const char AAAddressSpace::ID = 0;
13737const char AANoAliasAddrSpace::ID = 0;
13738const char AAAllocationInfo::ID = 0;
13739const char AAIndirectCallInfo::ID = 0;
13740const char AAGlobalValueInfo::ID = 0;
13741const char AADenormalFPMath::ID = 0;
13742
13743// Macro magic to create the static generator function for attributes that
13744// follow the naming scheme.
13745
13746#define SWITCH_PK_INV(CLASS, PK, POS_NAME) \
13747 case IRPosition::PK: \
13748 llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");
13749
13750#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX) \
13751 case IRPosition::PK: \
13752 AA = new (A.Allocator) CLASS##SUFFIX(IRP, A); \
13753 ++NumAAs; \
13754 break;
13755
13756#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13757 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13758 CLASS *AA = nullptr; \
13759 switch (IRP.getPositionKind()) { \
13760 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13761 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13762 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13763 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13764 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13765 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13766 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13767 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13768 } \
13769 return *AA; \
13770 }
13771
13772#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13773 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13774 CLASS *AA = nullptr; \
13775 switch (IRP.getPositionKind()) { \
13776 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13777 SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function") \
13778 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13779 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13780 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13781 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13782 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13783 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13784 } \
13785 return *AA; \
13786 }
13787
13788#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS) \
13789 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13790 CLASS *AA = nullptr; \
13791 switch (IRP.getPositionKind()) { \
13792 SWITCH_PK_CREATE(CLASS, IRP, POS, SUFFIX) \
13793 default: \
13794 llvm_unreachable("Cannot create " #CLASS " for position otherthan " #POS \
13795 " position!"); \
13796 } \
13797 return *AA; \
13798 }
13799
13800#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13801 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13802 CLASS *AA = nullptr; \
13803 switch (IRP.getPositionKind()) { \
13804 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13805 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13806 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13807 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13808 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13809 SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned) \
13810 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13811 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13812 } \
13813 return *AA; \
13814 }
13815
13816#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13817 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13818 CLASS *AA = nullptr; \
13819 switch (IRP.getPositionKind()) { \
13820 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13821 SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument") \
13822 SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating") \
13823 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13824 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned") \
13825 SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument") \
13826 SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site") \
13827 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13828 } \
13829 return *AA; \
13830 }
13831
13832#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS) \
13833 CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) { \
13834 CLASS *AA = nullptr; \
13835 switch (IRP.getPositionKind()) { \
13836 SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid") \
13837 SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned") \
13838 SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function) \
13839 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite) \
13840 SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating) \
13841 SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument) \
13842 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned) \
13843 SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument) \
13844 } \
13845 return *AA; \
13846 }
13847
13857
13875
13880
13885
13892
13894
13895#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
13896#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
13897#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
13898#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
13899#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
13900#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
13901#undef SWITCH_PK_CREATE
13902#undef SWITCH_PK_INV
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
unsigned uint64_t
AMDGPU Register Bank Select
Rewrite undef for PHI
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
This file contains the simple types necessary to represent the attributes associated with functions a...
#define STATS_DECLTRACK(NAME, TYPE, MSG)
static std::optional< Constant * > askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA, const IRPosition &IRP, Type &Ty)
static cl::opt< unsigned, true > MaxPotentialValues("attributor-max-potential-values", cl::Hidden, cl::desc("Maximum number of potential values to be " "tracked for each position."), cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues), cl::init(7))
static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA, StateType &S, const IRPosition::CallBaseContext *CBContext=nullptr)
Clamp the information known for all returned values of a function (identified by QueryingAA) into S.
#define STATS_DECLTRACK_FN_ATTR(NAME)
#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxPotentialValuesIterations("attributor-max-potential-values-iterations", cl::Hidden, cl::desc("Maximum number of iterations we keep dismantling potential values."), cl::init(64))
#define STATS_DECLTRACK_CS_ATTR(NAME)
#define PIPE_OPERATOR(CLASS)
#define STATS_DECLTRACK_ARG_ATTR(NAME)
static const Value * stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Val, const DataLayout &DL, APInt &Offset, bool GetMinOffset, bool AllowNonInbounds, bool UseAssumed=false)
#define STATS_DECLTRACK_CSRET_ATTR(NAME)
static cl::opt< bool > ManifestInternal("attributor-manifest-internal", cl::Hidden, cl::desc("Manifest Attributor internal string attributes."), cl::init(false))
static Value * constructPointer(Value *Ptr, int64_t Offset, IRBuilder< NoFolder > &IRB)
Helper function to create a pointer based on Ptr, and advanced by Offset bytes.
#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define BUILD_STAT_NAME(NAME, TYPE)
static bool isDenselyPacked(Type *Ty, const DataLayout &DL)
Checks if a type could have padding bytes.
#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static const Value * getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA, const Value *Ptr, int64_t &BytesOffset, const DataLayout &DL, bool AllowNonInbounds=false)
static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I, bool HeaderOnly, CycleRef *CPtr=nullptr)
#define STATS_DECLTRACK_FNRET_ATTR(NAME)
#define STATS_DECLTRACK_CSARG_ATTR(NAME)
#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION(POS, SUFFIX, CLASS)
#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
static cl::opt< int > MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128), cl::Hidden)
#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)
#define STATS_DECL(NAME, TYPE, MSG)
basic Basic Alias true
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isReachableImpl(SmallVectorImpl< BasicBlock * > &Worklist, const StopSetT &StopSet, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT, const LoopInfo *LI, const CycleInfo *CI)
Definition CFG.cpp:145
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares an analysis pass that computes CycleInfo for LLVM IR, specialized from GenericCycl...
static uint64_t align(uint64_t Size)
DXIL Forward Handle Accesses
DXIL Resource Access
dxil translate DXIL Translate Metadata
This file defines DenseMapInfo traits for DenseMap.
This file defines the DenseMap class.
#define Check(C,...)
static Value * getCondition(Instruction *I)
Hexagon Common GEP
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
#define T
#define T1
static unsigned getAddressSpace(const Value *V, unsigned MaxLookup)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
uint64_t IntrinsicInst * II
if(PassOpts->AAPipeline)
static StringRef getName(Value *V)
Basic Register Allocator
dot regions Print regions of function to dot true view regions View regions of function(with no function bodies)"
Remove Loads Into Fake Uses
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
bool IsDead
Func getContext().diagnose(DiagnosticInfoUnsupported(Func
std::pair< BasicBlock *, BasicBlock * > Edge
This file contains some templates that are useful if you are working with the STL at all.
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
This pass exposes codegen information to IR-level passes.
static unsigned getBitWidth(Type *Ty, const DataLayout &DL)
Returns the bitwidth of the given scalar or pointer type.
Value * RHS
Value * LHS
static unsigned getSize(unsigned Kind)
LLVM_ABI AACallGraphNode * operator*() const
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A trivial helper function to check to see if the specified pointers are no-alias.
Class for arbitrary precision integers.
Definition APInt.h:78
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
CallBase * getInstruction() const
Return the underlying instruction.
bool isCallbackCall() const
Return true if this ACS represents a callback call.
bool isDirectCall() const
Return true if this ACS represents a direct call.
static LLVM_ABI void getCallbackUses(const CallBase &CB, SmallVectorImpl< const Use * > &CallbackUses)
Add operand uses of CB that represent callback uses into CallbackUses.
int getCallArgOperandNo(Argument &Arg) const
Return the operand index of the underlying instruction associated with Arg.
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
unsigned getAddressSpace() const
Return the address space for the allocation.
LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const
Get allocation size in bytes.
This class represents an incoming formal argument to a Function.
Definition Argument.h:32
LLVM_ABI bool hasNoAliasAttr() const
Return true if this argument has the noalias attribute.
Definition Function.cpp:270
LLVM_ABI bool onlyReadsMemory() const
Return true if this argument has the readonly or readnone attribute.
Definition Function.cpp:306
LLVM_ABI bool hasPointeeInMemoryValueAttr() const
Return true if this argument has the byval, sret, inalloca, preallocated, or byref attribute.
Definition Function.cpp:173
LLVM_ABI bool hasReturnedAttr() const
Return true if this argument has the returned attribute.
Definition Function.cpp:294
LLVM_ABI bool hasByValAttr() const
Return true if this argument has the byval attribute.
Definition Function.cpp:130
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:106
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
LLVM_ABI FPClassTest getNoFPClass() const
Return the FPClassTest for nofpclass.
LLVM_ABI Attribute::AttrKind getKindAsEnum() const
Return the attribute's kind as an enum (Attribute::AttrKind).
LLVM_ABI MemoryEffects getMemoryEffects() const
Returns memory effects.
AttrKind
This enumeration lists the attributes that can be associated with parameters, function results,...
Definition Attributes.h:125
static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)
static bool isEnumAttrKind(AttrKind Kind)
Definition Attributes.h:139
bool isValid() const
Return true if the attribute is any kind of attribute.
Definition Attributes.h:266
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:469
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
BinaryOps getOpcode() const
Definition InstrTypes.h:409
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI bool isMustTailCall() const
Tests if this call site must be tail call optimized.
LLVM_ABI bool isIndirectCall() const
Return true if the callsite is an indirect call.
bool isCallee(Value::const_user_iterator UI) const
Determine whether the passed iterator points to the callee operand's Use.
Value * getCalledOperand() const
const Use & getCalledOperandUse() const
Attribute getFnAttr(StringRef Kind) const
Get the attribute of a given kind for the function.
const Use & getArgOperandUse(unsigned i) const
Wrappers for getting the Use of a call argument.
LLVM_ABI std::optional< ConstantRange > getRange() const
If this return value has a range attribute, return the value range of the argument.
Value * getArgOperand(unsigned i) const
bool isBundleOperand(unsigned Idx) const
Return true if the operand at index Idx is a bundle operand.
bool isConvergent() const
Determine if the invoke is convergent.
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned getArgOperandNo(const Use *U) const
Given a use for a arg operand, get the arg operand number that corresponds to it.
unsigned arg_size() const
bool isArgOperand(const Use *U) const
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static CaptureInfo none()
Create CaptureInfo that does not capture any components of the pointer.
Definition ModRef.h:427
Instruction::CastOps getOpcode() const
Return the opcode of this CastInst.
Definition InstrTypes.h:674
LLVM_ABI bool isIntegerCast() const
There are several places where we need to know if a cast instruction only deals with integer source a...
Type * getDestTy() const
Return the destination type, as a convenience.
Definition InstrTypes.h:681
bool isEquality() const
Determine if this is an equals/not equals predicate.
Definition InstrTypes.h:978
bool isFalseWhenEqual() const
This is just a convenience.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
@ ICMP_NE
not equal
Definition InstrTypes.h:762
bool isTrueWhenEqual() const
This is just a convenience.
Predicate getPredicate() const
Return the predicate for this instruction.
Definition InstrTypes.h:828
Conditional Branch instruction.
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
static ConstantAsMetadata * get(Constant *C)
Definition Metadata.h:548
static LLVM_ABI Constant * getExtractElement(Constant *Vec, Constant *Idx, Type *OnlyIfReducedTy=nullptr)
static LLVM_ABI ConstantInt * getTrue(LLVMContext &Context)
This class represents a range of values.
const APInt & getLower() const
Return the lower value for this range.
LLVM_ABI bool isFullSet() const
Return true if this set contains all of the elements possible for this data-type.
LLVM_ABI bool isEmptySet() const
Return true if this set contains no members.
bool isSingleElement() const
Return true if this set contains exactly one member.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
const APInt & getUpper() const
Return the upper value for this range.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
unsigned getProgramAddressSpace() const
Definition DataLayout.h:269
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:758
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:763
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
iterator end()
Definition DenseMap.h:687
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:828
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
const BasicBlock & getEntryBlock() const
Definition Function.h:794
Argument * arg_iterator
Definition Function.h:73
iterator_range< arg_iterator > args()
Definition Function.h:877
const Function & getFunction() const
Definition Function.h:167
size_t arg_size() const
Definition Function.h:886
Argument * getArg(unsigned i) const
Definition Function.h:871
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:734
BlockT * getHeader(CycleRef C) const
CycleRef getCycle(const BlockT *Block) const
Find the innermost cycle containing Block.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
bool hasLocalLinkage() const
PointerType * getType() const
Global values are always pointers.
static LLVM_ABI bool compare(const APInt &LHS, const APInt &RHS, ICmpInst::Predicate Pred)
Return result of LHS Pred RHS comparison.
Value * CreatePtrAdd(Value *Ptr, Value *Offset, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition IRBuilder.h:2101
ConstantInt * getInt64(uint64_t C)
Get a constant 64-bit value.
Definition IRBuilder.h:479
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2918
LLVM_ABI Instruction * clone() const
Create a copy of 'this' instruction that is identical in all ways except the following:
LLVM_ABI bool isLifetimeStartOrEnd() const LLVM_READONLY
Return true if the instruction is a llvm.lifetime.start or llvm.lifetime.end marker.
bool mayReadOrWriteMemory() const
Return true if this instruction may read or write memory.
LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY
Return true if this instruction may modify memory.
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI bool mayHaveSideEffects() const LLVM_READONLY
Return true if the instruction may have side effects.
bool isTerminator() const
LLVM_ABI bool mayReadFromMemory() const LLVM_READONLY
Return true if this instruction may read memory.
iterator_range< user_iterator > users()
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI ConstantRange getConstantRange(Value *V, Instruction *CtxI, bool UndefAllowed)
Return the ConstantRange constraint that is known to hold for the specified value at the specified in...
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
static LLVM_ABI MDNode * getMostGenericRange(MDNode *A, MDNode *B)
bool empty() const
Definition MapVector.h:79
static MemoryEffectsBase readOnly()
Definition ModRef.h:133
bool doesNotAccessMemory() const
Whether this function accesses no memory.
Definition ModRef.h:246
static MemoryEffectsBase argMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:143
static MemoryEffectsBase inaccessibleMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:149
bool onlyAccessesInaccessibleMem() const
Whether this function only (at most) accesses inaccessible memory.
Definition ModRef.h:265
ModRefInfo getModRef(Location Loc) const
Get ModRefInfo for the given Location.
Definition ModRef.h:219
bool onlyAccessesArgPointees() const
Whether this function only (at most) accesses argument memory.
Definition ModRef.h:255
bool onlyReadsMemory() const
Whether this function only (at most) reads memory.
Definition ModRef.h:249
static MemoryEffectsBase writeOnly()
Definition ModRef.h:138
static MemoryEffectsBase inaccessibleOrArgMemOnly(ModRefInfo MR=ModRefInfo::ModRef)
Definition ModRef.h:166
static MemoryEffectsBase none()
Definition ModRef.h:128
bool onlyAccessesInaccessibleOrArgMem() const
Whether this function only (at most) accesses argument and inaccessible memory.
Definition ModRef.h:305
static MemoryEffectsBase unknown()
Definition ModRef.h:123
static LLVM_ABI std::optional< MemoryLocation > getOrNone(const Instruction *Inst)
static SizeOffsetValue unknown()
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
Value * getReturnValue() const
Convenience accessor. Returns null if there is no return value.
LLVM_ABI SCEVUse getSCEVAtScope(const SCEV *S, const Loop *L)
Return a SCEV expression for the specified value at the specified scope in the program.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI unsigned getSmallConstantMaxTripCount(const Loop *L, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Returns the upper bound of the loop trip count as a normal unsigned value.
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition DataLayout.h:743
TypeSize getElementOffset(unsigned Idx) const
Definition DataLayout.h:774
TypeSize getElementOffsetInBits(unsigned Idx) const
Definition DataLayout.h:779
Class to represent struct types.
unsigned getNumElements() const
Random access to the elements.
Type * getElementType(unsigned N) const
LLVM_ABI bool areTypesABICompatible(const Function *Caller, const Function *Callee, ArrayRef< Type * > Types) const
LLVM_ABI unsigned getAssumedAddrSpace(const Value *V) const
LLVM_ABI bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) const
Return true if the given instruction (assumed to be a memory access instruction) has a volatile varia...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getIntegerBitWidth() const
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:277
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
bool isPtrOrPtrVectorTy() const
Return true if this is a pointer type or a vector of pointer types.
Definition Type.h:280
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
static UncondBrInst * Create(BasicBlock *Target, InsertPosition InsertBefore=nullptr)
BasicBlock * getSuccessor(unsigned i=0) const
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
Value * get() const
Definition Use.h:55
const Use & getOperandUse(unsigned i) const
Definition User.h:220
LLVM_ABI bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
Definition User.cpp:119
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:25
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
ValueT lookup(const KeyT &Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition ValueMap.h:167
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
static constexpr uint64_t MaximumAlignment
Definition Value.h:801
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
LLVM_ABI const Value * stripAndAccumulateConstantOffsets(const DataLayout &DL, APInt &Offset, bool AllowNonInbounds, bool AllowInvariantGroup=false, function_ref< bool(Value &Value, APInt &Offset)> ExternalAnalysis=nullptr, bool LookThroughIntToPtr=false) const
Accumulate the constant offset this value has compared to a base pointer.
bool use_empty() const
Definition Value.h:348
static constexpr unsigned MaxAlignmentExponent
The maximum alignment for instructions.
Definition Value.h:800
iterator_range< use_iterator > uses()
Definition Value.h:382
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an std::string.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
Definition Attributor.h:165
LLVM_ABI bool isAssumedReadNone(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readnone.
LLVM_ABI bool isAssumedReadOnly(Attributor &A, const IRPosition &IRP, const AbstractAttribute &QueryingAA, bool &IsKnown)
Return true if IRP is readonly.
raw_ostream & operator<<(raw_ostream &OS, const RangeTy &R)
Definition Attributor.h:327
LLVM_ABI std::optional< Value * > combineOptionalValuesInAAValueLatice(const std::optional< Value * > &A, const std::optional< Value * > &B, Type *Ty)
Return the combination of A and B such that the result is a possible value of both.
LLVM_ABI bool isValidAtPosition(const ValueAndContext &VAC, InformationCache &InfoCache)
Return true if the value of VAC is a valid at the position of VAC, that is a constant,...
LLVM_ABI bool isAssumedThreadLocalObject(Attributor &A, Value &Obj, const AbstractAttribute &QueryingAA)
Return true if Obj is assumed to be a thread local object.
LLVM_ABI bool isGPUConstantAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU constant address space for the target triple...
LLVM_ABI bool isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA, const Value &V, bool ForAnalysisOnly=true)
Return true if V is dynamically unique, that is, there are no two "instances" of V at runtime with di...
LLVM_ABI bool getPotentialCopiesOfStoredValue(Attributor &A, StoreInst &SI, SmallSetVector< Value *, 4 > &PotentialCopies, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values of the one stored by SI into PotentialCopies.
LLVM_ABI bool isGPUSharedAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU shared address space for the target triple i...
LLVM_ABI bool isGPULocalAddressSpace(const Module &M, unsigned AS)
Check if the given address space AS corresponds to a GPU local/private address space for the target t...
SmallPtrSet< Instruction *, 4 > InstExclusionSetTy
Definition Attributor.h:166
LLVM_ABI bool isGPU(const Module &M)
Return true iff M target a GPU (and we can use GPU AS reasoning).
ValueScope
Flags to distinguish intra-procedural queries from potentially inter-procedural queries.
Definition Attributor.h:186
@ Intraprocedural
Definition Attributor.h:187
@ Interprocedural
Definition Attributor.h:188
LLVM_ABI bool isValidInScope(const Value &V, const Function *Scope)
Return true if V is a valid value in Scope, that is a constant or an instruction/argument of Scope.
LLVM_ABI bool isPotentiallyReachable(Attributor &A, const Instruction &FromI, const Instruction &ToI, const AbstractAttribute &QueryingAA, const AA::InstExclusionSetTy *ExclusionSet=nullptr, std::function< bool(const Function &F)> GoBackwardsCB=nullptr)
Return true if ToI is potentially reachable from FromI without running into any instruction in Exclus...
LLVM_ABI bool isNoSyncInst(Attributor &A, const Instruction &I, const AbstractAttribute &QueryingAA)
Return true if I is a nosync instruction.
bool hasAssumedIRAttr(Attributor &A, const AbstractAttribute *QueryingAA, const IRPosition &IRP, DepClassTy DepClass, bool &IsKnown, bool IgnoreSubsumingPositions=false, const AAType **AAPtr=nullptr)
Helper to avoid creating an AA for IR Attributes that might already be set.
LLVM_ABI bool getPotentiallyLoadedValues(Attributor &A, LoadInst &LI, SmallSetVector< Value *, 4 > &PotentialValues, SmallSetVector< Instruction *, 4 > &PotentialValueOrigins, const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation, bool OnlyExact=false)
Collect all potential values LI could read into PotentialValues.
LLVM_ABI Value * getWithType(Value &V, Type &Ty)
Try to convert V to type Ty without introducing new instructions.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:83
@ Unsupported
This operation is completely unsupported on the target.
Offsets
Offsets in bytes from the start of the input buffer.
@ SingleThread
Synchronized with respect to signal handlers executing in the same thread.
Definition LLVMContext.h:55
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
@ Valid
The data is already valid.
initializer< Ty > init(const Ty &Val)
LocationClass< Ty > location(Ty &L)
unsigned combineHashValue(unsigned a, unsigned b)
Simplistic combination of 32-bit hash values into 32-bit hash values.
ElementType
The element type of an SRV or UAV resource.
Definition DXILABI.h:68
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract_or_null(Y &&MD)
Extract a Value from Metadata, if any, allowing null.
Definition Metadata.h:720
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
iterator end() const
Definition BasicBlock.h:89
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Length
Definition DWP.cpp:577
bool operator<(int64_t V1, const APSInt &V2)
Definition APSInt.h:360
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt gcd(const DynamicAPInt &A, const DynamicAPInt &B)
LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)
Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
LLVM_ABI Constant * getInitialValueOfAllocation(const Value *V, const TargetLibraryInfo *TLI, Type *Ty)
If this is a call to an allocation function that initializes memory to a fixed value,...
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
@ Known
Known to have no common set bits.
@ Undef
Value of the register doesn't matter.
auto pred_end(const MachineBasicBlock *BB)
unsigned getPointerAddressSpace(const Type *T)
Definition SPIRVUtils.h:393
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
LLVM_ABI bool isRemovableAlloc(const CallBase *V, const TargetLibraryInfo *TLI)
Return true if this is a call to an allocation function that does not have side effects that we are r...
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition APFloat.h:1721
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
LLVM_ABI Value * getAllocAlignment(const CallBase *V, const TargetLibraryInfo *TLI)
Gets the alignment argument for an aligned_alloc-like function, using either built-in knowledge based...
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
LLVM_ABI Value * simplifyInstructionWithOperands(Instruction *I, ArrayRef< Value * > NewOps, const SimplifyQuery &Q)
Like simplifyInstruction but the operands of I are replaced with NewOps.
Value * GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, const DataLayout &DL, bool AllowNonInbounds=true)
Analyze the specified pointer to see if it can be expressed as a base pointer plus a constant offset.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
LLVM_ABI bool isNoAliasCall(const Value *V)
Return true if this pointer is returned by a noalias function.
MemoryEffectsBase< IRMemLocation > MemoryEffects
Summary of how a function affects memory in the program.
Definition ModRef.h:356
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
LLVM_ABI bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true, bool IgnoreUBImplyingAttrs=true)
Return true if the instruction does not have any effects besides calculating the result and does not ...
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
LLVM_ABI ConstantRange getConstantRangeFromMetadata(const MDNode &RangeMD)
Parse out a conservative ConstantRange from !range metadata.
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:366
const Value * getPointerOperand(const Value *V)
A helper function that returns the pointer operand of a load, store or GEP instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
PotentialValuesState< std::pair< AA::ValueAndContext, AA::ValueScope > > PotentialLLVMValuesState
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)
Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isPointerTy(const Type *T)
Definition SPIRVUtils.h:381
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI bool wouldInstructionBeTriviallyDead(const Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction would have no side effects if it was not used.
Definition Local.cpp:413
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI CallBase & promoteCall(CallBase &CB, Function *Callee, CastInst **RetBitCast=nullptr)
Promote the given indirect call site to unconditionally call Callee.
LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth, bool MustPreserveProvenance=false)
This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI bool hasAssumption(const Function &F, const KnownAssumptionString &AssumptionStr)
Return true if F has the assumption AssumptionStr attached.
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.
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.
LLVM_ABI bool isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(const CallBase *Call, bool MustPreserveOffset, bool MustPreserveProvenance=false)
launder.invariant.group and similar intrinsics return a pointer that aliases their argument,...
DWARFExpression::Operation Op
LLVM_ABI bool isGuaranteedNotToBeUndefOrPoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Return true if this function can prove that V does not have undef bits and is never poison.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Value * getFreedOperand(const CallBase *CB, const TargetLibraryInfo *TLI)
If this if a call to a free function, return the freed operand.
ChangeStatus clampStateAndIndicateChange(StateType &S, const StateType &R)
Helper function to clamp a state S of type StateType with the information in R and indicate/return if...
constexpr unsigned BitWidth
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
ChangeStatus
{
Definition Attributor.h:477
LLVM_ABI std::optional< APInt > getAllocSize(const CallBase *CB, const TargetLibraryInfo *TLI, function_ref< const Value *(const Value *)> Mapper=[](const Value *V) { return V;})
Return the size of the requested allocation.
LLVM_ABI DenseSet< StringRef > getAssumptions(const Function &F)
Return the set of all assumptions for the function F.
Align assumeAligned(uint64_t Value)
Treats the value 0 as a 1, so Align is always at least 1.
Definition Alignment.h:105
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
@ OPTIONAL
The target may be valid if the source is not.
Definition Attributor.h:489
@ NONE
Do not track a dependence between source and target.
Definition Attributor.h:490
@ REQUIRED
The target cannot be valid if the source is not.
Definition Attributor.h:488
LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)
Determine what kind of capture behaviour U may exhibit.
LLVM_ABI Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)
Given operands for a CmpInst, fold the result or return null.
LLVM_ABI bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:391
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
bool capturesNothing(CaptureComponents CC)
Definition ModRef.h:375
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
bool capturesAnyProvenance(CaptureComponents CC)
Definition ModRef.h:400
constexpr StringRef AssumptionAttrKey
The key we use for assumption attributes.
Definition Assumptions.h:29
constexpr bool isCallableCC(CallingConv::ID CC)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
A type to track pointer/struct usage and accesses for AAPointerInfo.
bool forallInterferingAccesses(AA::RangeTy Range, F CB) const
See AAPointerInfo::forallInterferingAccesses.
AAPointerInfo::const_bin_iterator end() const
ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I, std::optional< Value * > Content, AAPointerInfo::AccessKind Kind, Type *Ty, Instruction *RemoteI=nullptr)
Add a new Access to the state at offset Offset and with size Size.
DenseMap< const Instruction *, SmallVector< unsigned > > RemoteIMap
AAPointerInfo::const_bin_iterator begin() const
AAPointerInfo::OffsetInfo ReturnedOffsets
Flag to determine if the underlying pointer is reaching a return statement in the associated function...
State(State &&SIS)=default
const AAPointerInfo::Access & getAccess(unsigned Index) const
SmallVector< AAPointerInfo::Access > AccessList
bool isAtFixpoint() const override
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_fpenv to a known denormal mod...
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all dereferenceable attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for llvm::GlobalValue information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for indirect call information interference.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface to track if a value leaves it's defining function instance.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract Attribute for computing reachability between functions.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool canReach(Attributor &A, const Function &Fn) const
If the function represented by this possition can reach Fn.
virtual bool instructionCanReach(Attributor &A, const Instruction &Inst, const Function &Fn, const AA::InstExclusionSetTy *ExclusionSet=nullptr) const =0
Can Inst reach Fn.
An abstract interface to determine reachability of point A to B.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for identifying pointers from which loads can be marked invariant.
static LLVM_ABI const char ID
Unique ID (due to the unique address).
An abstract interface for liveness abstract attribute.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for memory access kind related attributes (readnone/readonly/writeonly).
bool isAssumedReadOnly() const
Return true if we assume that the underlying value is not accessed (=written) in its respective scope...
bool isKnownReadNone() const
Return true if we know that the underlying value is not read or accessed in its respective scope.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
bool isAssumedReadNone() const
Return true if we assume that the underlying value is not read or accessed in its respective scope.
An abstract interface for all memory location attributes (readnone/argmemonly/inaccessiblememonly/ina...
static LLVM_ABI std::string getMemoryLocationsAsStr(MemoryLocationsKind MLK)
Return the locations encoded by MLK as a readable string.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
StateType::base_t MemoryLocationsKind
An abstract interface for all nonnull attributes.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for potential address space information.
static LLVM_ABI const char ID
Unique ID (due to the unique address)
An abstract interface for all noalias attributes.
static LLVM_ABI bool isImpliedByIR(Attributor &A, const IRPosition &IRP, Attribute::AttrKind ImpliedAttributeKind, bool IgnoreSubsumingPositions=false)
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.
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:245
static constexpr int64_t Unknown
Definition Attributor.h:324
static RangeTy getUnknown()
Definition Attributor.h:251
Value * getValue() const
Definition Attributor.h:198
const Instruction * getCtxI() const
Definition Attributor.h:199
Base struct for all "concrete attribute" deductions.
void print(raw_ostream &OS) const
Helper functions, for debug purposes only.
virtual StateType & getState()=0
Return the internal abstract state for inspection.
AbstractState StateType
An interface to query the internal state of an abstract attribute.
virtual bool isAtFixpoint() const =0
Return if this abstract state is fixed, thus does not need to be updated if information changes as it...
virtual bool isValidState() const =0
Return if this abstract state is in a valid state.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
Definition Alignment.h:82
static constexpr Align fromLog2(unsigned Log2Value)
Returns an alignment of 1 << Log2Value bytes.
Definition Alignment.h:73
std::function< void( const ArgumentReplacementInfo &, Function &, Function::arg_iterator)> CalleeRepairCBTy
Callee repair callback type.
const Argument & getReplacedArg() const
std::function< void(const ArgumentReplacementInfo &, AbstractCallSite, SmallVectorImpl< Value * > &)> ACSRepairCBTy
Abstract call site (ACS) repair callback type.
The fixpoint analysis framework that orchestrates the attribute deduction.
std::function< std::optional< Value * >( const IRPosition &, const AbstractAttribute *, bool &)> SimplifictionCallbackTy
Register CB as a simplification callback.
Specialization of the integer state for a bit-wise encoding.
BitIntegerState & addKnownBits(base_t Bits)
Add the bits in BitsEncoding to the "known bits".
Simple wrapper for a single bit (boolean) state.
static constexpr DenormalFPEnv getDefault()
static unsigned getHashValue(const Access &A)
static bool isEqual(const Access &LHS, const Access &RHS)
static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B)
static unsigned getHashValue(const AA::RangeTy &Range)
DenseMapInfo< std::pair< const Instruction *, const ToTy * > > PairDMI
static bool isEqual(const ReachabilityQueryInfo< ToTy > *LHS, const ReachabilityQueryInfo< ToTy > *RHS)
DenseMapInfo< const AA::InstExclusionSetTy * > InstSetDMI
static unsigned getHashValue(const ReachabilityQueryInfo< ToTy > *RQI)
An information struct used to provide DenseMap with the various necessary components for a given valu...
State for dereferenceable attribute.
IncIntegerState DerefBytesState
State representing for dereferenceable bytes.
ChangeStatus manifest(Attributor &A) override
See AbstractAttribute::manifest(...).
Helper to describe and deal with positions in the LLVM-IR.
Definition Attributor.h:573
Function * getAssociatedFunction() const
Return the associated function, if any.
Definition Attributor.h:704
static const IRPosition callsite_returned(const CallBase &CB)
Create a position describing the returned value of CB.
Definition Attributor.h:641
static const IRPosition returned(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the returned value of F.
Definition Attributor.h:623
LLVM_ABI Argument * getAssociatedArgument() const
Return the associated argument, if any.
static const IRPosition value(const Value &V, const CallBaseContext *CBContext=nullptr)
Create a position describing the value of V.
Definition Attributor.h:597
CallBase CallBaseContext
Definition Attributor.h:576
int getCalleeArgNo() const
Return the callee argument number of the associated value if it is an argument or call site argument,...
Definition Attributor.h:791
static const IRPosition inst(const Instruction &I, const CallBaseContext *CBContext=nullptr)
Create a position describing the instruction I.
Definition Attributor.h:609
static const IRPosition callsite_argument(const CallBase &CB, unsigned ArgNo)
Create a position describing the argument of CB at position ArgNo.
Definition Attributor.h:646
@ IRP_ARGUMENT
An attribute for a function argument.
Definition Attributor.h:587
@ IRP_RETURNED
An attribute for the function return value.
Definition Attributor.h:583
@ IRP_CALL_SITE
An attribute for a call site (function scope).
Definition Attributor.h:586
@ IRP_CALL_SITE_RETURNED
An attribute for a call site return value.
Definition Attributor.h:584
@ IRP_FUNCTION
An attribute for a function (scope).
Definition Attributor.h:585
@ IRP_CALL_SITE_ARGUMENT
An attribute for a call site argument.
Definition Attributor.h:588
@ IRP_INVALID
An invalid position.
Definition Attributor.h:580
Instruction * getCtxI() const
Return the context instruction, if any.
Definition Attributor.h:757
static const IRPosition argument(const Argument &Arg, const CallBaseContext *CBContext=nullptr)
Create a position describing the argument Arg.
Definition Attributor.h:630
Type * getAssociatedType() const
Return the type this abstract attribute is associated with.
Definition Attributor.h:780
static const IRPosition function(const Function &F, const CallBaseContext *CBContext=nullptr)
Create a position describing the function scope of F.
Definition Attributor.h:616
const CallBaseContext * getCallBaseContext() const
Get the call base context from the position.
Definition Attributor.h:897
Value & getAssociatedValue() const
Return the value this abstract attribute is associated with.
Definition Attributor.h:771
Value & getAnchorValue() const
Return the value this abstract attribute is anchored with.
Definition Attributor.h:690
int getCallSiteArgNo() const
Return the call site argument number of the associated value if it is an argument or call site argume...
Definition Attributor.h:800
static const IRPosition function_scope(const IRPosition &IRP, const CallBaseContext *CBContext=nullptr)
Create a position with function scope matching the "context" of IRP.
Definition Attributor.h:669
Kind getPositionKind() const
Return the associated position kind.
Definition Attributor.h:847
bool isArgumentPosition() const
Return true if the position is an argument or call site argument.
Definition Attributor.h:879
static const IRPosition callsite_function(const CallBase &CB)
Create a position describing the function scope of CB.
Definition Attributor.h:636
Function * getAnchorScope() const
Return the Function surrounding the anchor value.
Definition Attributor.h:745
Data structure to hold cached (LLVM-IR) information.
TargetLibraryInfo * getTargetLibraryInfoForFunction(const Function &F)
Return TargetLibraryInfo for function F.
bool isOnlyUsedByAssume(const Instruction &I) const
AP::Result * getAnalysisResultForFunction(const Function &F, bool CachedOnly=false)
Return the analysis result from a pass AP for function F.
ConstantRange getKnown() const
Return the known state encoding.
ConstantRange getAssumed() const
Return the assumed state encoding.
base_t getAssumed() const
Return the assumed state encoding.
Helper that allows to insert a new assumption string in the known assumption set by creating a (stati...
Definition Assumptions.h:37
FPClassTest getKnownFPClasses() const
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(...).
CaptureComponents ResultCC
Components captured by the return value of the user of this Use.
LLVM_ABI bool unionAssumed(std::optional< Value * > Other)
Merge Other into the currently assumed simplified value.
std::optional< Value * > SimplifiedAssociatedValue
An assumed simplified value.
Type * Ty
The type of the original value.