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