//===- AttributorAttributes.cpp - Attributes for Attributor deduction -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// See the Attributor.h file comment and the class descriptions in that file for
// more information.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO/Attributor.h"

#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/CycleAnalysis.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LazyValueInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Assumptions.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include "llvm/IR/IntrinsicsNVPTX.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/NoFolder.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <cassert>
#include <numeric>
#include <optional>

using namespace llvm;

#define DEBUG_TYPE "attributor"

static cl::opt<bool> ManifestInternal(
    "attributor-manifest-internal", cl::Hidden,
    cl::desc("Manifest Attributor internal string attributes."),
    cl::init(false));

static cl::opt<int> MaxHeapToStackSize("max-heap-to-stack-size", cl::init(128),
                                       cl::Hidden);

template <>
unsigned llvm::PotentialConstantIntValuesState::MaxPotentialValues = 0;

template <> unsigned llvm::PotentialLLVMValuesState::MaxPotentialValues = -1;

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 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));

STATISTIC(NumAAs, "Number of abstract attributes created");

// Some helper macros to deal with statistics tracking.
//
// Usage:
// For simple IR attribute tracking overload trackStatistics in the abstract
// attribute and choose the right STATS_DECLTRACK_********* macro,
// e.g.,:
//  void trackStatistics() const override {
//    STATS_DECLTRACK_ARG_ATTR(returned)
//  }
// If there is a single "increment" side one can use the macro
// STATS_DECLTRACK with a custom message. If there are multiple increment
// sides, STATS_DECL and STATS_TRACK can also be used separately.
//
#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME)                                     \
  ("Number of " #TYPE " marked '" #NAME "'")
#define BUILD_STAT_NAME(NAME, TYPE) NumIR##TYPE##_##NAME
#define STATS_DECL_(NAME, MSG) STATISTIC(NAME, MSG);
#define STATS_DECL(NAME, TYPE, MSG)                                            \
  STATS_DECL_(BUILD_STAT_NAME(NAME, TYPE), MSG);
#define STATS_TRACK(NAME, TYPE) ++(BUILD_STAT_NAME(NAME, TYPE));
#define STATS_DECLTRACK(NAME, TYPE, MSG)                                       \
  {                                                                            \
    STATS_DECL(NAME, TYPE, MSG)                                                \
    STATS_TRACK(NAME, TYPE)                                                    \
  }
#define STATS_DECLTRACK_ARG_ATTR(NAME)                                         \
  STATS_DECLTRACK(NAME, Arguments, BUILD_STAT_MSG_IR_ATTR(arguments, NAME))
#define STATS_DECLTRACK_CSARG_ATTR(NAME)                                       \
  STATS_DECLTRACK(NAME, CSArguments,                                           \
                  BUILD_STAT_MSG_IR_ATTR(call site arguments, NAME))
#define STATS_DECLTRACK_FN_ATTR(NAME)                                          \
  STATS_DECLTRACK(NAME, Function, BUILD_STAT_MSG_IR_ATTR(functions, NAME))
#define STATS_DECLTRACK_CS_ATTR(NAME)                                          \
  STATS_DECLTRACK(NAME, CS, BUILD_STAT_MSG_IR_ATTR(call site, NAME))
#define STATS_DECLTRACK_FNRET_ATTR(NAME)                                       \
  STATS_DECLTRACK(NAME, FunctionReturn,                                        \
                  BUILD_STAT_MSG_IR_ATTR(function returns, NAME))
#define STATS_DECLTRACK_CSRET_ATTR(NAME)                                       \
  STATS_DECLTRACK(NAME, CSReturn,                                              \
                  BUILD_STAT_MSG_IR_ATTR(call site returns, NAME))
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)                                    \
  STATS_DECLTRACK(NAME, Floating,                                              \
                  ("Number of floating values known to be '" #NAME "'"))

// Specialization of the operator<< for abstract attributes subclasses. This
// disambiguates situations where multiple operators are applicable.
namespace llvm {
#define PIPE_OPERATOR(CLASS)                                                   \
  raw_ostream &operator<<(raw_ostream &OS, const CLASS &AA) {                  \
    return OS << static_cast<const AbstractAttribute &>(AA);                   \
  }

PIPE_OPERATOR(AAIsDead)
PIPE_OPERATOR(AANoUnwind)
PIPE_OPERATOR(AANoSync)
PIPE_OPERATOR(AANoRecurse)
PIPE_OPERATOR(AANonConvergent)
PIPE_OPERATOR(AAWillReturn)
PIPE_OPERATOR(AANoReturn)
PIPE_OPERATOR(AANonNull)
PIPE_OPERATOR(AAMustProgress)
PIPE_OPERATOR(AANoAlias)
PIPE_OPERATOR(AADereferenceable)
PIPE_OPERATOR(AAAlign)
PIPE_OPERATOR(AAInstanceInfo)
PIPE_OPERATOR(AANoCapture)
PIPE_OPERATOR(AAValueSimplify)
PIPE_OPERATOR(AANoFree)
PIPE_OPERATOR(AAHeapToStack)
PIPE_OPERATOR(AAIntraFnReachability)
PIPE_OPERATOR(AAMemoryBehavior)
PIPE_OPERATOR(AAMemoryLocation)
PIPE_OPERATOR(AAValueConstantRange)
PIPE_OPERATOR(AAPrivatizablePtr)
PIPE_OPERATOR(AAUndefinedBehavior)
PIPE_OPERATOR(AAPotentialConstantValues)
PIPE_OPERATOR(AAPotentialValues)
PIPE_OPERATOR(AANoUndef)
PIPE_OPERATOR(AANoFPClass)
PIPE_OPERATOR(AACallEdges)
PIPE_OPERATOR(AAInterFnReachability)
PIPE_OPERATOR(AAPointerInfo)
PIPE_OPERATOR(AAAssumptionInfo)
PIPE_OPERATOR(AAUnderlyingObjects)
PIPE_OPERATOR(AAAddressSpace)

#undef PIPE_OPERATOR

template <>
ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
                                                     const DerefState &R) {
  ChangeStatus CS0 =
      clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
  ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
  return CS0 | CS1;
}

} // namespace llvm

static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
                         bool HeaderOnly, Cycle **CPtr = nullptr) {
  if (!CI)
    return true;
  auto *BB = I->getParent();
  auto *C = CI->getCycle(BB);
  if (!C)
    return false;
  if (CPtr)
    *CPtr = C;
  return !HeaderOnly || BB == C->getHeader();
}

/// Checks if a type could have padding bytes.
static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {
  // There is no size information, so be conservative.
  if (!Ty->isSized())
    return false;

  // If the alloc size is not equal to the storage size, then there are padding
  // bytes. For x86_fp80 on x86-64, size: 80 alloc size: 128.
  if (DL.getTypeSizeInBits(Ty) != DL.getTypeAllocSizeInBits(Ty))
    return false;

  // FIXME: This isn't the right way to check for padding in vectors with
  // non-byte-size elements.
  if (VectorType *SeqTy = dyn_cast<VectorType>(Ty))
    return isDenselyPacked(SeqTy->getElementType(), DL);

  // For array types, check for padding within members.
  if (ArrayType *SeqTy = dyn_cast<ArrayType>(Ty))
    return isDenselyPacked(SeqTy->getElementType(), DL);

  if (!isa<StructType>(Ty))
    return true;

  // Check for padding within and between elements of a struct.
  StructType *StructTy = cast<StructType>(Ty);
  const StructLayout *Layout = DL.getStructLayout(StructTy);
  uint64_t StartPos = 0;
  for (unsigned I = 0, E = StructTy->getNumElements(); I < E; ++I) {
    Type *ElTy = StructTy->getElementType(I);
    if (!isDenselyPacked(ElTy, DL))
      return false;
    if (StartPos != Layout->getElementOffsetInBits(I))
      return false;
    StartPos += DL.getTypeAllocSizeInBits(ElTy);
  }

  return true;
}

/// Get pointer operand of memory accessing instruction. If \p I is
/// not a memory accessing instruction, return nullptr. If \p AllowVolatile,
/// is set to false and the instruction is volatile, return nullptr.
static const Value *getPointerOperand(const Instruction *I,
                                      bool AllowVolatile) {
  if (!AllowVolatile && I->isVolatile())
    return nullptr;

  if (auto *LI = dyn_cast<LoadInst>(I)) {
    return LI->getPointerOperand();
  }

  if (auto *SI = dyn_cast<StoreInst>(I)) {
    return SI->getPointerOperand();
  }

  if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(I)) {
    return CXI->getPointerOperand();
  }

  if (auto *RMWI = dyn_cast<AtomicRMWInst>(I)) {
    return RMWI->getPointerOperand();
  }

  return nullptr;
}

/// Helper function to create a pointer of type \p ResTy, based on \p Ptr, and
/// advanced by \p Offset bytes. To aid later analysis the method tries to build
/// getelement pointer instructions that traverse the natural type of \p Ptr if
/// possible. If that fails, the remaining offset is adjusted byte-wise, hence
/// through a cast to i8*.
///
/// TODO: This could probably live somewhere more prominantly if it doesn't
///       already exist.
static Value *constructPointer(Type *ResTy, Type *PtrElemTy, Value *Ptr,
                               int64_t Offset, IRBuilder<NoFolder> &IRB,
                               const DataLayout &DL) {
  assert(Offset >= 0 && "Negative offset not supported yet!");
  LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
                    << "-bytes as " << *ResTy << "\n");

  if (Offset) {
    Type *Ty = PtrElemTy;
    APInt IntOffset(DL.getIndexTypeSizeInBits(Ptr->getType()), Offset);
    SmallVector<APInt> IntIndices = DL.getGEPIndicesForOffset(Ty, IntOffset);

    SmallVector<Value *, 4> ValIndices;
    std::string GEPName = Ptr->getName().str();
    for (const APInt &Index : IntIndices) {
      ValIndices.push_back(IRB.getInt(Index));
      GEPName += "." + std::to_string(Index.getZExtValue());
    }

    // Create a GEP for the indices collected above.
    Ptr = IRB.CreateGEP(PtrElemTy, Ptr, ValIndices, GEPName);

    // If an offset is left we use byte-wise adjustment.
    if (IntOffset != 0) {
      Ptr = IRB.CreateBitCast(Ptr, IRB.getInt8PtrTy());
      Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt(IntOffset),
                          GEPName + ".b" + Twine(IntOffset.getZExtValue()));
    }
  }

  // Ensure the result has the requested type.
  Ptr = IRB.CreatePointerBitCastOrAddrSpaceCast(Ptr, ResTy,
                                                Ptr->getName() + ".cast");

  LLVM_DEBUG(dbgs() << "Constructed pointer: " << *Ptr << "\n");
  return Ptr;
}

static const Value *
stripAndAccumulateOffsets(Attributor &A, const AbstractAttribute &QueryingAA,
                          const Value *Val, const DataLayout &DL, APInt &Offset,
                          bool GetMinOffset, bool AllowNonInbounds,
                          bool UseAssumed = false) {

  auto AttributorAnalysis = [&](Value &V, APInt &ROffset) -> bool {
    const IRPosition &Pos = IRPosition::value(V);
    // Only track dependence if we are going to use the assumed info.
    const AAValueConstantRange *ValueConstantRangeAA =
        A.getAAFor<AAValueConstantRange>(QueryingAA, Pos,
                                         UseAssumed ? DepClassTy::OPTIONAL
                                                    : DepClassTy::NONE);
    if (!ValueConstantRangeAA)
      return false;
    ConstantRange Range = UseAssumed ? ValueConstantRangeAA->getAssumed()
                                     : ValueConstantRangeAA->getKnown();
    if (Range.isFullSet())
      return false;

    // We can only use the lower part of the range because the upper part can
    // be higher than what the value can really be.
    if (GetMinOffset)
      ROffset = Range.getSignedMin();
    else
      ROffset = Range.getSignedMax();
    return true;
  };

  return Val->stripAndAccumulateConstantOffsets(DL, Offset, AllowNonInbounds,
                                                /* AllowInvariant */ true,
                                                AttributorAnalysis);
}

static const Value *
getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
                        const Value *Ptr, int64_t &BytesOffset,
                        const DataLayout &DL, bool AllowNonInbounds = false) {
  APInt OffsetAPInt(DL.getIndexTypeSizeInBits(Ptr->getType()), 0);
  const Value *Base =
      stripAndAccumulateOffsets(A, QueryingAA, Ptr, DL, OffsetAPInt,
                                /* GetMinOffset */ true, AllowNonInbounds);

  BytesOffset = OffsetAPInt.getSExtValue();
  return Base;
}

/// Clamp the information known for all returned values of a function
/// (identified by \p QueryingAA) into \p S.
template <typename AAType, typename StateType = typename AAType::StateType,
          Attribute::AttrKind IRAttributeKind = Attribute::None,
          bool RecurseForSelectAndPHI = true>
static void clampReturnedValueStates(
    Attributor &A, const AAType &QueryingAA, StateType &S,
    const IRPosition::CallBaseContext *CBContext = nullptr) {
  LLVM_DEBUG(dbgs() << "[Attributor] Clamp return value states for "
                    << QueryingAA << " into " << S << "\n");

  assert((QueryingAA.getIRPosition().getPositionKind() ==
              IRPosition::IRP_RETURNED ||
          QueryingAA.getIRPosition().getPositionKind() ==
              IRPosition::IRP_CALL_SITE_RETURNED) &&
         "Can only clamp returned value states for a function returned or call "
         "site returned position!");

  // Use an optional state as there might not be any return values and we want
  // to join (IntegerState::operator&) the state of all there are.
  std::optional<StateType> T;

  // Callback for each possibly returned value.
  auto CheckReturnValue = [&](Value &RV) -> bool {
    const IRPosition &RVPos = IRPosition::value(RV, CBContext);
    // If possible, use the hasAssumedIRAttr interface.
    if (IRAttributeKind != Attribute::None) {
      bool IsKnown;
      return AA::hasAssumedIRAttr<IRAttributeKind>(
          A, &QueryingAA, RVPos, DepClassTy::REQUIRED, IsKnown);
    }

    const AAType *AA =
        A.getAAFor<AAType>(QueryingAA, RVPos, DepClassTy::REQUIRED);
    if (!AA)
      return false;
    LLVM_DEBUG(dbgs() << "[Attributor] RV: " << RV
                      << " AA: " << AA->getAsStr(&A) << " @ " << RVPos << "\n");
    const StateType &AAS = AA->getState();
    if (!T)
      T = StateType::getBestState(AAS);
    *T &= AAS;
    LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " RV State: " << T
                      << "\n");
    return T->isValidState();
  };

  if (!A.checkForAllReturnedValues(CheckReturnValue, QueryingAA,
                                   AA::ValueScope::Intraprocedural,
                                   RecurseForSelectAndPHI))
    S.indicatePessimisticFixpoint();
  else if (T)
    S ^= *T;
}

namespace {
/// Helper class for generic deduction: return value -> returned position.
template <typename AAType, typename BaseType,
          typename StateType = typename BaseType::StateType,
          bool PropagateCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = Attribute::None,
          bool RecurseForSelectAndPHI = true>
struct AAReturnedFromReturnedValues : public BaseType {
  AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
      : BaseType(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    StateType S(StateType::getBestState(this->getState()));
    clampReturnedValueStates<AAType, StateType, IRAttributeKind, RecurseForSelectAndPHI>(
        A, *this, S,
        PropagateCallBaseContext ? this->getCallBaseContext() : nullptr);
    // TODO: If we know we visited all returned values, thus no are assumed
    // dead, we can take the known information from the state T.
    return clampStateAndIndicateChange<StateType>(this->getState(), S);
  }
};

/// Clamp the information known at all call sites for a given argument
/// (identified by \p QueryingAA) into \p S.
template <typename AAType, typename StateType = typename AAType::StateType,
          Attribute::AttrKind IRAttributeKind = Attribute::None>
static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
                                        StateType &S) {
  LLVM_DEBUG(dbgs() << "[Attributor] Clamp call site argument states for "
                    << QueryingAA << " into " << S << "\n");

  assert(QueryingAA.getIRPosition().getPositionKind() ==
             IRPosition::IRP_ARGUMENT &&
         "Can only clamp call site argument states for an argument position!");

  // Use an optional state as there might not be any return values and we want
  // to join (IntegerState::operator&) the state of all there are.
  std::optional<StateType> T;

  // The argument number which is also the call site argument number.
  unsigned ArgNo = QueryingAA.getIRPosition().getCallSiteArgNo();

  auto CallSiteCheck = [&](AbstractCallSite ACS) {
    const IRPosition &ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
    // Check if a coresponding argument was found or if it is on not associated
    // (which can happen for callback calls).
    if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
      return false;

    // If possible, use the hasAssumedIRAttr interface.
    if (IRAttributeKind != Attribute::None) {
      bool IsKnown;
      return AA::hasAssumedIRAttr<IRAttributeKind>(
          A, &QueryingAA, ACSArgPos, DepClassTy::REQUIRED, IsKnown);
    }

    const AAType *AA =
        A.getAAFor<AAType>(QueryingAA, ACSArgPos, DepClassTy::REQUIRED);
    if (!AA)
      return false;
    LLVM_DEBUG(dbgs() << "[Attributor] ACS: " << *ACS.getInstruction()
                      << " AA: " << AA->getAsStr(&A) << " @" << ACSArgPos
                      << "\n");
    const StateType &AAS = AA->getState();
    if (!T)
      T = StateType::getBestState(AAS);
    *T &= AAS;
    LLVM_DEBUG(dbgs() << "[Attributor] AA State: " << AAS << " CSA State: " << T
                      << "\n");
    return T->isValidState();
  };

  bool UsedAssumedInformation = false;
  if (!A.checkForAllCallSites(CallSiteCheck, QueryingAA, true,
                              UsedAssumedInformation))
    S.indicatePessimisticFixpoint();
  else if (T)
    S ^= *T;
}

/// This function is the bridge between argument position and the call base
/// context.
template <typename AAType, typename BaseType,
          typename StateType = typename AAType::StateType,
          Attribute::AttrKind IRAttributeKind = Attribute::None>
bool getArgumentStateFromCallBaseContext(Attributor &A,
                                         BaseType &QueryingAttribute,
                                         IRPosition &Pos, StateType &State) {
  assert((Pos.getPositionKind() == IRPosition::IRP_ARGUMENT) &&
         "Expected an 'argument' position !");
  const CallBase *CBContext = Pos.getCallBaseContext();
  if (!CBContext)
    return false;

  int ArgNo = Pos.getCallSiteArgNo();
  assert(ArgNo >= 0 && "Invalid Arg No!");
  const IRPosition CBArgPos = IRPosition::callsite_argument(*CBContext, ArgNo);

  // If possible, use the hasAssumedIRAttr interface.
  if (IRAttributeKind != Attribute::None) {
    bool IsKnown;
    return AA::hasAssumedIRAttr<IRAttributeKind>(
        A, &QueryingAttribute, CBArgPos, DepClassTy::REQUIRED, IsKnown);
  }

  const auto *AA =
      A.getAAFor<AAType>(QueryingAttribute, CBArgPos, DepClassTy::REQUIRED);
  if (!AA)
    return false;
  const StateType &CBArgumentState =
      static_cast<const StateType &>(AA->getState());

  LLVM_DEBUG(dbgs() << "[Attributor] Briding Call site context to argument"
                    << "Position:" << Pos << "CB Arg state:" << CBArgumentState
                    << "\n");

  // NOTE: If we want to do call site grouping it should happen here.
  State ^= CBArgumentState;
  return true;
}

/// Helper class for generic deduction: call site argument -> argument position.
template <typename AAType, typename BaseType,
          typename StateType = typename AAType::StateType,
          bool BridgeCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = Attribute::None>
struct AAArgumentFromCallSiteArguments : public BaseType {
  AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
      : BaseType(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    StateType S = StateType::getBestState(this->getState());

    if (BridgeCallBaseContext) {
      bool Success =
          getArgumentStateFromCallBaseContext<AAType, BaseType, StateType,
                                              IRAttributeKind>(
              A, *this, this->getIRPosition(), S);
      if (Success)
        return clampStateAndIndicateChange<StateType>(this->getState(), S);
    }
    clampCallSiteArgumentStates<AAType, StateType, IRAttributeKind>(A, *this,
                                                                    S);

    // TODO: If we know we visited all incoming values, thus no are assumed
    // dead, we can take the known information from the state T.
    return clampStateAndIndicateChange<StateType>(this->getState(), S);
  }
};

/// Helper class for generic replication: function returned -> cs returned.
template <typename AAType, typename BaseType,
          typename StateType = typename BaseType::StateType,
          bool IntroduceCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = Attribute::None>
struct AACallSiteReturnedFromReturned : public BaseType {
  AACallSiteReturnedFromReturned(const IRPosition &IRP, Attributor &A)
      : BaseType(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    assert(this->getIRPosition().getPositionKind() ==
               IRPosition::IRP_CALL_SITE_RETURNED &&
           "Can only wrap function returned positions for call site returned "
           "positions!");
    auto &S = this->getState();

    const Function *AssociatedFunction =
        this->getIRPosition().getAssociatedFunction();
    if (!AssociatedFunction)
      return S.indicatePessimisticFixpoint();

    CallBase &CBContext = cast<CallBase>(this->getAnchorValue());
    if (IntroduceCallBaseContext)
      LLVM_DEBUG(dbgs() << "[Attributor] Introducing call base context:"
                        << CBContext << "\n");

    IRPosition FnPos = IRPosition::returned(
        *AssociatedFunction, IntroduceCallBaseContext ? &CBContext : nullptr);

    // If possible, use the hasAssumedIRAttr interface.
    if (IRAttributeKind != Attribute::None) {
      bool IsKnown;
      if (!AA::hasAssumedIRAttr<IRAttributeKind>(A, this, FnPos,
                                                 DepClassTy::REQUIRED, IsKnown))
        return S.indicatePessimisticFixpoint();
      return ChangeStatus::UNCHANGED;
    }

    const AAType *AA = A.getAAFor<AAType>(*this, FnPos, DepClassTy::REQUIRED);
    if (!AA)
      return S.indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(S, AA->getState());
  }
};

/// Helper function to accumulate uses.
template <class AAType, typename StateType = typename AAType::StateType>
static void followUsesInContext(AAType &AA, Attributor &A,
                                MustBeExecutedContextExplorer &Explorer,
                                const Instruction *CtxI,
                                SetVector<const Use *> &Uses,
                                StateType &State) {
  auto EIt = Explorer.begin(CtxI), EEnd = Explorer.end(CtxI);
  for (unsigned u = 0; u < Uses.size(); ++u) {
    const Use *U = Uses[u];
    if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
      bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
      if (Found && AA.followUseInMBEC(A, U, UserI, State))
        for (const Use &Us : UserI->uses())
          Uses.insert(&Us);
    }
  }
}

/// Use the must-be-executed-context around \p I to add information into \p S.
/// The AAType class is required to have `followUseInMBEC` method with the
/// following signature and behaviour:
///
/// bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I)
/// U - Underlying use.
/// I - The user of the \p U.
/// Returns true if the value should be tracked transitively.
///
template <class AAType, typename StateType = typename AAType::StateType>
static void followUsesInMBEC(AAType &AA, Attributor &A, StateType &S,
                             Instruction &CtxI) {
  MustBeExecutedContextExplorer *Explorer =
      A.getInfoCache().getMustBeExecutedContextExplorer();
  if (!Explorer)
    return;

  // Container for (transitive) uses of the associated value.
  SetVector<const Use *> Uses;
  for (const Use &U : AA.getIRPosition().getAssociatedValue().uses())
    Uses.insert(&U);

  followUsesInContext<AAType>(AA, A, *Explorer, &CtxI, Uses, S);

  if (S.isAtFixpoint())
    return;

  SmallVector<const BranchInst *, 4> BrInsts;
  auto Pred = [&](const Instruction *I) {
    if (const BranchInst *Br = dyn_cast<BranchInst>(I))
      if (Br->isConditional())
        BrInsts.push_back(Br);
    return true;
  };

  // Here, accumulate conditional branch instructions in the context. We
  // explore the child paths and collect the known states. The disjunction of
  // those states can be merged to its own state. Let ParentState_i be a state
  // to indicate the known information for an i-th branch instruction in the
  // context. ChildStates are created for its successors respectively.
  //
  // ParentS_1 = ChildS_{1, 1} /\ ChildS_{1, 2} /\ ... /\ ChildS_{1, n_1}
  // ParentS_2 = ChildS_{2, 1} /\ ChildS_{2, 2} /\ ... /\ ChildS_{2, n_2}
  //      ...
  // ParentS_m = ChildS_{m, 1} /\ ChildS_{m, 2} /\ ... /\ ChildS_{m, n_m}
  //
  // Known State |= ParentS_1 \/ ParentS_2 \/... \/ ParentS_m
  //
  // FIXME: Currently, recursive branches are not handled. For example, we
  // can't deduce that ptr must be dereferenced in below function.
  //
  // void f(int a, int c, int *ptr) {
  //    if(a)
  //      if (b) {
  //        *ptr = 0;
  //      } else {
  //        *ptr = 1;
  //      }
  //    else {
  //      if (b) {
  //        *ptr = 0;
  //      } else {
  //        *ptr = 1;
  //      }
  //    }
  // }

  Explorer->checkForAllContext(&CtxI, Pred);
  for (const BranchInst *Br : BrInsts) {
    StateType ParentState;

    // The known state of the parent state is a conjunction of children's
    // known states so it is initialized with a best state.
    ParentState.indicateOptimisticFixpoint();

    for (const BasicBlock *BB : Br->successors()) {
      StateType ChildState;

      size_t BeforeSize = Uses.size();
      followUsesInContext(AA, A, *Explorer, &BB->front(), Uses, ChildState);

      // Erase uses which only appear in the child.
      for (auto It = Uses.begin() + BeforeSize; It != Uses.end();)
        It = Uses.erase(It);

      ParentState &= ChildState;
    }

    // Use only known state.
    S += ParentState;
  }
}
} // namespace

/// ------------------------ PointerInfo ---------------------------------------

namespace llvm {
namespace AA {
namespace PointerInfo {

struct State;

} // namespace PointerInfo
} // namespace AA

/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
template <>
struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {
  using Access = AAPointerInfo::Access;
  static inline Access getEmptyKey();
  static inline Access getTombstoneKey();
  static unsigned getHashValue(const Access &A);
  static bool isEqual(const Access &LHS, const Access &RHS);
};

/// Helper that allows RangeTy as a key in a DenseMap.
template <> struct DenseMapInfo<AA::RangeTy> {
  static inline AA::RangeTy getEmptyKey() {
    auto EmptyKey = DenseMapInfo<int64_t>::getEmptyKey();
    return AA::RangeTy{EmptyKey, EmptyKey};
  }

  static inline AA::RangeTy getTombstoneKey() {
    auto TombstoneKey = DenseMapInfo<int64_t>::getTombstoneKey();
    return AA::RangeTy{TombstoneKey, TombstoneKey};
  }

  static unsigned getHashValue(const AA::RangeTy &Range) {
    return detail::combineHashValue(
        DenseMapInfo<int64_t>::getHashValue(Range.Offset),
        DenseMapInfo<int64_t>::getHashValue(Range.Size));
  }

  static bool isEqual(const AA::RangeTy &A, const AA::RangeTy B) {
    return A == B;
  }
};

/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
/// but the instruction
struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {
  using Base = DenseMapInfo<Instruction *>;
  using Access = AAPointerInfo::Access;
  static inline Access getEmptyKey();
  static inline Access getTombstoneKey();
  static unsigned getHashValue(const Access &A);
  static bool isEqual(const Access &LHS, const Access &RHS);
};

} // namespace llvm

/// A type to track pointer/struct usage and accesses for AAPointerInfo.
struct AA::PointerInfo::State : public AbstractState {
  /// Return the best possible representable state.
  static State getBestState(const State &SIS) { return State(); }

  /// Return the worst possible representable state.
  static State getWorstState(const State &SIS) {
    State R;
    R.indicatePessimisticFixpoint();
    return R;
  }

  State() = default;
  State(State &&SIS) = default;

  const State &getAssumed() const { return *this; }

  /// See AbstractState::isValidState().
  bool isValidState() const override { return BS.isValidState(); }

  /// See AbstractState::isAtFixpoint().
  bool isAtFixpoint() const override { return BS.isAtFixpoint(); }

  /// See AbstractState::indicateOptimisticFixpoint().
  ChangeStatus indicateOptimisticFixpoint() override {
    BS.indicateOptimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractState::indicatePessimisticFixpoint().
  ChangeStatus indicatePessimisticFixpoint() override {
    BS.indicatePessimisticFixpoint();
    return ChangeStatus::CHANGED;
  }

  State &operator=(const State &R) {
    if (this == &R)
      return *this;
    BS = R.BS;
    AccessList = R.AccessList;
    OffsetBins = R.OffsetBins;
    RemoteIMap = R.RemoteIMap;
    return *this;
  }

  State &operator=(State &&R) {
    if (this == &R)
      return *this;
    std::swap(BS, R.BS);
    std::swap(AccessList, R.AccessList);
    std::swap(OffsetBins, R.OffsetBins);
    std::swap(RemoteIMap, R.RemoteIMap);
    return *this;
  }

  /// Add a new Access to the state at offset \p Offset and with size \p Size.
  /// The access is associated with \p I, writes \p Content (if anything), and
  /// is of kind \p Kind. If an Access already exists for the same \p I and same
  /// \p RemoteI, the two are combined, potentially losing information about
  /// offset and size. The resulting access must now be moved from its original
  /// OffsetBin to the bin for its new offset.
  ///
  /// \Returns CHANGED, if the state changed, UNCHANGED otherwise.
  ChangeStatus addAccess(Attributor &A, const AAPointerInfo::RangeList &Ranges,
                         Instruction &I, std::optional<Value *> Content,
                         AAPointerInfo::AccessKind Kind, Type *Ty,
                         Instruction *RemoteI = nullptr);

  using OffsetBinsTy = DenseMap<RangeTy, SmallSet<unsigned, 4>>;

  using const_bin_iterator = OffsetBinsTy::const_iterator;
  const_bin_iterator begin() const { return OffsetBins.begin(); }
  const_bin_iterator end() const { return OffsetBins.end(); }

  const AAPointerInfo::Access &getAccess(unsigned Index) const {
    return AccessList[Index];
  }

protected:
  // Every memory instruction results in an Access object. We maintain a list of
  // all Access objects that we own, along with the following maps:
  //
  // - OffsetBins: RangeTy -> { Access }
  // - RemoteIMap: RemoteI x LocalI -> Access
  //
  // A RemoteI is any instruction that accesses memory. RemoteI is different
  // from LocalI if and only if LocalI is a call; then RemoteI is some
  // instruction in the callgraph starting from LocalI. Multiple paths in the
  // callgraph from LocalI to RemoteI may produce multiple accesses, but these
  // are all combined into a single Access object. This may result in loss of
  // information in RangeTy in the Access object.
  SmallVector<AAPointerInfo::Access> AccessList;
  OffsetBinsTy OffsetBins;
  DenseMap<const Instruction *, SmallVector<unsigned>> RemoteIMap;

  /// See AAPointerInfo::forallInterferingAccesses.
  bool forallInterferingAccesses(
      AA::RangeTy Range,
      function_ref<bool(const AAPointerInfo::Access &, bool)> CB) const {
    if (!isValidState())
      return false;

    for (const auto &It : OffsetBins) {
      AA::RangeTy ItRange = It.getFirst();
      if (!Range.mayOverlap(ItRange))
        continue;
      bool IsExact = Range == ItRange && !Range.offsetOrSizeAreUnknown();
      for (auto Index : It.getSecond()) {
        auto &Access = AccessList[Index];
        if (!CB(Access, IsExact))
          return false;
      }
    }
    return true;
  }

  /// See AAPointerInfo::forallInterferingAccesses.
  bool forallInterferingAccesses(
      Instruction &I,
      function_ref<bool(const AAPointerInfo::Access &, bool)> CB,
      AA::RangeTy &Range) const {
    if (!isValidState())
      return false;

    auto LocalList = RemoteIMap.find(&I);
    if (LocalList == RemoteIMap.end()) {
      return true;
    }

    for (unsigned Index : LocalList->getSecond()) {
      for (auto &R : AccessList[Index]) {
        Range &= R;
        if (Range.offsetAndSizeAreUnknown())
          break;
      }
    }
    return forallInterferingAccesses(Range, CB);
  }

private:
  /// State to track fixpoint and validity.
  BooleanState BS;
};

ChangeStatus AA::PointerInfo::State::addAccess(
    Attributor &A, const AAPointerInfo::RangeList &Ranges, Instruction &I,
    std::optional<Value *> Content, AAPointerInfo::AccessKind Kind, Type *Ty,
    Instruction *RemoteI) {
  RemoteI = RemoteI ? RemoteI : &I;

  // Check if we have an access for this instruction, if not, simply add it.
  auto &LocalList = RemoteIMap[RemoteI];
  bool AccExists = false;
  unsigned AccIndex = AccessList.size();
  for (auto Index : LocalList) {
    auto &A = AccessList[Index];
    if (A.getLocalInst() == &I) {
      AccExists = true;
      AccIndex = Index;
      break;
    }
  }

  auto AddToBins = [&](const AAPointerInfo::RangeList &ToAdd) {
    LLVM_DEBUG(if (ToAdd.size()) dbgs()
                   << "[AAPointerInfo] Inserting access in new offset bins\n";);

    for (auto Key : ToAdd) {
      LLVM_DEBUG(dbgs() << "    key " << Key << "\n");
      OffsetBins[Key].insert(AccIndex);
    }
  };

  if (!AccExists) {
    AccessList.emplace_back(&I, RemoteI, Ranges, Content, Kind, Ty);
    assert((AccessList.size() == AccIndex + 1) &&
           "New Access should have been at AccIndex");
    LocalList.push_back(AccIndex);
    AddToBins(AccessList[AccIndex].getRanges());
    return ChangeStatus::CHANGED;
  }

  // Combine the new Access with the existing Access, and then update the
  // mapping in the offset bins.
  AAPointerInfo::Access Acc(&I, RemoteI, Ranges, Content, Kind, Ty);
  auto &Current = AccessList[AccIndex];
  auto Before = Current;
  Current &= Acc;
  if (Current == Before)
    return ChangeStatus::UNCHANGED;

  auto &ExistingRanges = Before.getRanges();
  auto &NewRanges = Current.getRanges();

  // Ranges that are in the old access but not the new access need to be removed
  // from the offset bins.
  AAPointerInfo::RangeList ToRemove;
  AAPointerInfo::RangeList::set_difference(ExistingRanges, NewRanges, ToRemove);
  LLVM_DEBUG(if (ToRemove.size()) dbgs()
                 << "[AAPointerInfo] Removing access from old offset bins\n";);

  for (auto Key : ToRemove) {
    LLVM_DEBUG(dbgs() << "    key " << Key << "\n");
    assert(OffsetBins.count(Key) && "Existing Access must be in some bin.");
    auto &Bin = OffsetBins[Key];
    assert(Bin.count(AccIndex) &&
           "Expected bin to actually contain the Access.");
    Bin.erase(AccIndex);
  }

  // Ranges that are in the new access but not the old access need to be added
  // to the offset bins.
  AAPointerInfo::RangeList ToAdd;
  AAPointerInfo::RangeList::set_difference(NewRanges, ExistingRanges, ToAdd);
  AddToBins(ToAdd);
  return ChangeStatus::CHANGED;
}

namespace {

/// A helper containing a list of offsets computed for a Use. Ideally this
/// list should be strictly ascending, but we ensure that only when we
/// actually translate the list of offsets to a RangeList.
struct OffsetInfo {
  using VecTy = SmallVector<int64_t>;
  using const_iterator = VecTy::const_iterator;
  VecTy Offsets;

  const_iterator begin() const { return Offsets.begin(); }
  const_iterator end() const { return Offsets.end(); }

  bool operator==(const OffsetInfo &RHS) const {
    return Offsets == RHS.Offsets;
  }

  bool operator!=(const OffsetInfo &RHS) const { return !(*this == RHS); }

  void insert(int64_t Offset) { Offsets.push_back(Offset); }
  bool isUnassigned() const { return Offsets.size() == 0; }

  bool isUnknown() const {
    if (isUnassigned())
      return false;
    if (Offsets.size() == 1)
      return Offsets.front() == AA::RangeTy::Unknown;
    return false;
  }

  void setUnknown() {
    Offsets.clear();
    Offsets.push_back(AA::RangeTy::Unknown);
  }

  void addToAll(int64_t Inc) {
    for (auto &Offset : Offsets) {
      Offset += Inc;
    }
  }

  /// Copy offsets from \p R into the current list.
  ///
  /// Ideally all lists should be strictly ascending, but we defer that to the
  /// actual use of the list. So we just blindly append here.
  void merge(const OffsetInfo &R) { Offsets.append(R.Offsets); }
};

#ifndef NDEBUG
static raw_ostream &operator<<(raw_ostream &OS, const OffsetInfo &OI) {
  ListSeparator LS;
  OS << "[";
  for (auto Offset : OI) {
    OS << LS << Offset;
  }
  OS << "]";
  return OS;
}
#endif // NDEBUG

struct AAPointerInfoImpl
    : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {
  using BaseTy = StateWrapper<AA::PointerInfo::State, AAPointerInfo>;
  AAPointerInfoImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return std::string("PointerInfo ") +
           (isValidState() ? (std::string("#") +
                              std::to_string(OffsetBins.size()) + " bins")
                           : "<invalid>");
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    return AAPointerInfo::manifest(A);
  }

  bool forallInterferingAccesses(
      AA::RangeTy Range,
      function_ref<bool(const AAPointerInfo::Access &, bool)> CB)
      const override {
    return State::forallInterferingAccesses(Range, CB);
  }

  bool forallInterferingAccesses(
      Attributor &A, const AbstractAttribute &QueryingAA, Instruction &I,
      bool FindInterferingWrites, bool FindInterferingReads,
      function_ref<bool(const Access &, bool)> UserCB, bool &HasBeenWrittenTo,
      AA::RangeTy &Range) const override {
    HasBeenWrittenTo = false;

    SmallPtrSet<const Access *, 8> DominatingWrites;
    SmallVector<std::pair<const Access *, bool>, 8> InterferingAccesses;

    Function &Scope = *I.getFunction();
    bool IsKnownNoSync;
    bool IsAssumedNoSync = AA::hasAssumedIRAttr<Attribute::NoSync>(
        A, &QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL,
        IsKnownNoSync);
    const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
        IRPosition::function(Scope), &QueryingAA, DepClassTy::NONE);
    bool AllInSameNoSyncFn = IsAssumedNoSync;
    bool InstIsExecutedByInitialThreadOnly =
        ExecDomainAA && ExecDomainAA->isExecutedByInitialThreadOnly(I);

    // If the function is not ending in aligned barriers, we need the stores to
    // be in aligned barriers. The load being in one is not sufficient since the
    // store might be executed by a thread that disappears after, causing the
    // aligned barrier guarding the load to unblock and the load to read a value
    // that has no CFG path to the load.
    bool InstIsExecutedInAlignedRegion =
        FindInterferingReads && ExecDomainAA &&
        ExecDomainAA->isExecutedInAlignedRegion(A, I);

    if (InstIsExecutedInAlignedRegion || InstIsExecutedByInitialThreadOnly)
      A.recordDependence(*ExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);

    InformationCache &InfoCache = A.getInfoCache();
    bool IsThreadLocalObj =
        AA::isAssumedThreadLocalObject(A, getAssociatedValue(), *this);

    // Helper to determine if we need to consider threading, which we cannot
    // right now. However, if the function is (assumed) nosync or the thread
    // executing all instructions is the main thread only we can ignore
    // threading. Also, thread-local objects do not require threading reasoning.
    // Finally, we can ignore threading if either access is executed in an
    // aligned region.
    auto CanIgnoreThreadingForInst = [&](const Instruction &I) -> bool {
      if (IsThreadLocalObj || AllInSameNoSyncFn)
        return true;
      const auto *FnExecDomainAA =
          I.getFunction() == &Scope
              ? ExecDomainAA
              : A.lookupAAFor<AAExecutionDomain>(
                    IRPosition::function(*I.getFunction()), &QueryingAA,
                    DepClassTy::NONE);
      if (!FnExecDomainAA)
        return false;
      if (InstIsExecutedInAlignedRegion ||
          (FindInterferingWrites &&
           FnExecDomainAA->isExecutedInAlignedRegion(A, I))) {
        A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
        return true;
      }
      if (InstIsExecutedByInitialThreadOnly &&
          FnExecDomainAA->isExecutedByInitialThreadOnly(I)) {
        A.recordDependence(*FnExecDomainAA, QueryingAA, DepClassTy::OPTIONAL);
        return true;
      }
      return false;
    };

    // Helper to determine if the access is executed by the same thread as the
    // given instruction, for now it is sufficient to avoid any potential
    // threading effects as we cannot deal with them anyway.
    auto CanIgnoreThreading = [&](const Access &Acc) -> bool {
      return CanIgnoreThreadingForInst(*Acc.getRemoteInst()) ||
             (Acc.getRemoteInst() != Acc.getLocalInst() &&
              CanIgnoreThreadingForInst(*Acc.getLocalInst()));
    };

    // TODO: Use inter-procedural reachability and dominance.
    bool IsKnownNoRecurse;
    AA::hasAssumedIRAttr<Attribute::NoRecurse>(
        A, this, IRPosition::function(Scope), DepClassTy::OPTIONAL,
        IsKnownNoRecurse);

    const bool UseDominanceReasoning =
        FindInterferingWrites && IsKnownNoRecurse;
    const DominatorTree *DT =
        InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(Scope);

    // Helper to check if a value has "kernel lifetime", that is it will not
    // outlive a GPU kernel. This is true for shared, constant, and local
    // globals on AMD and NVIDIA GPUs.
    auto HasKernelLifetime = [&](Value *V, Module &M) {
      if (!AA::isGPU(M))
        return false;
      switch (AA::GPUAddressSpace(V->getType()->getPointerAddressSpace())) {
      case AA::GPUAddressSpace::Shared:
      case AA::GPUAddressSpace::Constant:
      case AA::GPUAddressSpace::Local:
        return true;
      default:
        return false;
      };
    };

    // The IsLiveInCalleeCB will be used by the AA::isPotentiallyReachable query
    // to determine if we should look at reachability from the callee. For
    // certain pointers we know the lifetime and we do not have to step into the
    // callee to determine reachability as the pointer would be dead in the
    // callee. See the conditional initialization below.
    std::function<bool(const Function &)> IsLiveInCalleeCB;

    if (auto *AI = dyn_cast<AllocaInst>(&getAssociatedValue())) {
      // If the alloca containing function is not recursive the alloca
      // must be dead in the callee.
      const Function *AIFn = AI->getFunction();
      bool IsKnownNoRecurse;
      if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(
              A, this, IRPosition::function(*AIFn), DepClassTy::OPTIONAL,
              IsKnownNoRecurse)) {
        IsLiveInCalleeCB = [AIFn](const Function &Fn) { return AIFn != &Fn; };
      }
    } else if (auto *GV = dyn_cast<GlobalValue>(&getAssociatedValue())) {
      // If the global has kernel lifetime we can stop if we reach a kernel
      // as it is "dead" in the (unknown) callees.
      if (HasKernelLifetime(GV, *GV->getParent()))
        IsLiveInCalleeCB = [](const Function &Fn) {
          return !Fn.hasFnAttribute("kernel");
        };
    }

    // Set of accesses/instructions that will overwrite the result and are
    // therefore blockers in the reachability traversal.
    AA::InstExclusionSetTy ExclusionSet;

    auto AccessCB = [&](const Access &Acc, bool Exact) {
      if (Exact && Acc.isMustAccess() && Acc.getRemoteInst() != &I) {
        if (Acc.isWrite() || (isa<LoadInst>(I) && Acc.isWriteOrAssumption()))
          ExclusionSet.insert(Acc.getRemoteInst());
      }

      if ((!FindInterferingWrites || !Acc.isWriteOrAssumption()) &&
          (!FindInterferingReads || !Acc.isRead()))
        return true;

      bool Dominates = FindInterferingWrites && DT && Exact &&
                       Acc.isMustAccess() &&
                       (Acc.getRemoteInst()->getFunction() == &Scope) &&
                       DT->dominates(Acc.getRemoteInst(), &I);
      if (Dominates)
        DominatingWrites.insert(&Acc);

      // Track if all interesting accesses are in the same `nosync` function as
      // the given instruction.
      AllInSameNoSyncFn &= Acc.getRemoteInst()->getFunction() == &Scope;

      InterferingAccesses.push_back({&Acc, Exact});
      return true;
    };
    if (!State::forallInterferingAccesses(I, AccessCB, Range))
      return false;

    HasBeenWrittenTo = !DominatingWrites.empty();

    // Dominating writes form a chain, find the least/lowest member.
    Instruction *LeastDominatingWriteInst = nullptr;
    for (const Access *Acc : DominatingWrites) {
      if (!LeastDominatingWriteInst) {
        LeastDominatingWriteInst = Acc->getRemoteInst();
      } else if (DT->dominates(LeastDominatingWriteInst,
                               Acc->getRemoteInst())) {
        LeastDominatingWriteInst = Acc->getRemoteInst();
      }
    }

    // Helper to determine if we can skip a specific write access.
    auto CanSkipAccess = [&](const Access &Acc, bool Exact) {
      if (!CanIgnoreThreading(Acc))
        return false;

      // Check read (RAW) dependences and write (WAR) dependences as necessary.
      // If we successfully excluded all effects we are interested in, the
      // access can be skipped.
      bool ReadChecked = !FindInterferingReads;
      bool WriteChecked = !FindInterferingWrites;

      // If the instruction cannot reach the access, the former does not
      // interfere with what the access reads.
      if (!ReadChecked) {
        if (!AA::isPotentiallyReachable(A, I, *Acc.getRemoteInst(), QueryingAA,
                                        &ExclusionSet, IsLiveInCalleeCB))
          ReadChecked = true;
      }
      // If the instruction cannot be reach from the access, the latter does not
      // interfere with what the instruction reads.
      if (!WriteChecked) {
        if (!AA::isPotentiallyReachable(A, *Acc.getRemoteInst(), I, QueryingAA,
                                        &ExclusionSet, IsLiveInCalleeCB))
          WriteChecked = true;
      }

      // If we still might be affected by the write of the access but there are
      // dominating writes in the function of the instruction
      // (HasBeenWrittenTo), we can try to reason that the access is overwritten
      // by them. This would have happend above if they are all in the same
      // function, so we only check the inter-procedural case. Effectively, we
      // want to show that there is no call after the dominting write that might
      // reach the access, and when it returns reach the instruction with the
      // updated value. To this end, we iterate all call sites, check if they
      // might reach the instruction without going through another access
      // (ExclusionSet) and at the same time might reach the access. However,
      // that is all part of AAInterFnReachability.
      if (!WriteChecked && HasBeenWrittenTo &&
          Acc.getRemoteInst()->getFunction() != &Scope) {

        const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
            QueryingAA, IRPosition::function(Scope), DepClassTy::OPTIONAL);

        // Without going backwards in the call tree, can we reach the access
        // from the least dominating write. Do not allow to pass the instruction
        // itself either.
        bool Inserted = ExclusionSet.insert(&I).second;

        if (!FnReachabilityAA ||
            !FnReachabilityAA->instructionCanReach(
                A, *LeastDominatingWriteInst,
                *Acc.getRemoteInst()->getFunction(), &ExclusionSet))
          WriteChecked = true;

        if (Inserted)
          ExclusionSet.erase(&I);
      }

      if (ReadChecked && WriteChecked)
        return true;

      if (!DT || !UseDominanceReasoning)
        return false;
      if (!DominatingWrites.count(&Acc))
        return false;
      return LeastDominatingWriteInst != Acc.getRemoteInst();
    };

    // Run the user callback on all accesses we cannot skip and return if
    // that succeeded for all or not.
    for (auto &It : InterferingAccesses) {
      if ((!AllInSameNoSyncFn && !IsThreadLocalObj && !ExecDomainAA) ||
          !CanSkipAccess(*It.first, It.second)) {
        if (!UserCB(*It.first, It.second))
          return false;
      }
    }
    return true;
  }

  ChangeStatus translateAndAddStateFromCallee(Attributor &A,
                                              const AAPointerInfo &OtherAA,
                                              CallBase &CB) {
    using namespace AA::PointerInfo;
    if (!OtherAA.getState().isValidState() || !isValidState())
      return indicatePessimisticFixpoint();

    const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);
    bool IsByval = OtherAAImpl.getAssociatedArgument()->hasByValAttr();

    // Combine the accesses bin by bin.
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    const auto &State = OtherAAImpl.getState();
    for (const auto &It : State) {
      for (auto Index : It.getSecond()) {
        const auto &RAcc = State.getAccess(Index);
        if (IsByval && !RAcc.isRead())
          continue;
        bool UsedAssumedInformation = false;
        AccessKind AK = RAcc.getKind();
        auto Content = A.translateArgumentToCallSiteContent(
            RAcc.getContent(), CB, *this, UsedAssumedInformation);
        AK = AccessKind(AK & (IsByval ? AccessKind::AK_R : AccessKind::AK_RW));
        AK = AccessKind(AK | (RAcc.isMayAccess() ? AK_MAY : AK_MUST));

        Changed |= addAccess(A, RAcc.getRanges(), CB, Content, AK,
                             RAcc.getType(), RAcc.getRemoteInst());
      }
    }
    return Changed;
  }

  ChangeStatus translateAndAddState(Attributor &A, const AAPointerInfo &OtherAA,
                                    const OffsetInfo &Offsets, CallBase &CB) {
    using namespace AA::PointerInfo;
    if (!OtherAA.getState().isValidState() || !isValidState())
      return indicatePessimisticFixpoint();

    const auto &OtherAAImpl = static_cast<const AAPointerInfoImpl &>(OtherAA);

    // Combine the accesses bin by bin.
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    const auto &State = OtherAAImpl.getState();
    for (const auto &It : State) {
      for (auto Index : It.getSecond()) {
        const auto &RAcc = State.getAccess(Index);
        for (auto Offset : Offsets) {
          auto NewRanges = Offset == AA::RangeTy::Unknown
                               ? AA::RangeTy::getUnknown()
                               : RAcc.getRanges();
          if (!NewRanges.isUnknown()) {
            NewRanges.addToAllOffsets(Offset);
          }
          Changed |=
              addAccess(A, NewRanges, CB, RAcc.getContent(), RAcc.getKind(),
                        RAcc.getType(), RAcc.getRemoteInst());
        }
      }
    }
    return Changed;
  }

  /// Statistic tracking for all AAPointerInfo implementations.
  /// See AbstractAttribute::trackStatistics().
  void trackPointerInfoStatistics(const IRPosition &IRP) const {}

  /// Dump the state into \p O.
  void dumpState(raw_ostream &O) {
    for (auto &It : OffsetBins) {
      O << "[" << It.first.Offset << "-" << It.first.Offset + It.first.Size
        << "] : " << It.getSecond().size() << "\n";
      for (auto AccIndex : It.getSecond()) {
        auto &Acc = AccessList[AccIndex];
        O << "     - " << Acc.getKind() << " - " << *Acc.getLocalInst() << "\n";
        if (Acc.getLocalInst() != Acc.getRemoteInst())
          O << "     -->                         " << *Acc.getRemoteInst()
            << "\n";
        if (!Acc.isWrittenValueYetUndetermined()) {
          if (isa_and_nonnull<Function>(Acc.getWrittenValue()))
            O << "       - c: func " << Acc.getWrittenValue()->getName()
              << "\n";
          else if (Acc.getWrittenValue())
            O << "       - c: " << *Acc.getWrittenValue() << "\n";
          else
            O << "       - c: <unknown>\n";
        }
      }
    }
  }
};

struct AAPointerInfoFloating : public AAPointerInfoImpl {
  using AccessKind = AAPointerInfo::AccessKind;
  AAPointerInfoFloating(const IRPosition &IRP, Attributor &A)
      : AAPointerInfoImpl(IRP, A) {}

  /// Deal with an access and signal if it was handled successfully.
  bool handleAccess(Attributor &A, Instruction &I,
                    std::optional<Value *> Content, AccessKind Kind,
                    SmallVectorImpl<int64_t> &Offsets, ChangeStatus &Changed,
                    Type &Ty) {
    using namespace AA::PointerInfo;
    auto Size = AA::RangeTy::Unknown;
    const DataLayout &DL = A.getDataLayout();
    TypeSize AccessSize = DL.getTypeStoreSize(&Ty);
    if (!AccessSize.isScalable())
      Size = AccessSize.getFixedValue();

    // Make a strictly ascending list of offsets as required by addAccess()
    llvm::sort(Offsets);
    auto *Last = std::unique(Offsets.begin(), Offsets.end());
    Offsets.erase(Last, Offsets.end());

    VectorType *VT = dyn_cast<VectorType>(&Ty);
    if (!VT || VT->getElementCount().isScalable() ||
        !Content.value_or(nullptr) || !isa<Constant>(*Content) ||
        (*Content)->getType() != VT ||
        DL.getTypeStoreSize(VT->getElementType()).isScalable()) {
      Changed = Changed | addAccess(A, {Offsets, Size}, I, Content, Kind, &Ty);
    } else {
      // Handle vector stores with constant content element-wise.
      // TODO: We could look for the elements or create instructions
      //       representing them.
      // TODO: We need to push the Content into the range abstraction
      //       (AA::RangeTy) to allow different content values for different
      //       ranges. ranges. Hence, support vectors storing different values.
      Type *ElementType = VT->getElementType();
      int64_t ElementSize = DL.getTypeStoreSize(ElementType).getFixedValue();
      auto *ConstContent = cast<Constant>(*Content);
      Type *Int32Ty = Type::getInt32Ty(ElementType->getContext());
      SmallVector<int64_t> ElementOffsets(Offsets.begin(), Offsets.end());

      for (int i = 0, e = VT->getElementCount().getFixedValue(); i != e; ++i) {
        Value *ElementContent = ConstantExpr::getExtractElement(
            ConstContent, ConstantInt::get(Int32Ty, i));

        // Add the element access.
        Changed = Changed | addAccess(A, {ElementOffsets, ElementSize}, I,
                                      ElementContent, Kind, ElementType);

        // Advance the offsets for the next element.
        for (auto &ElementOffset : ElementOffsets)
          ElementOffset += ElementSize;
      }
    }
    return true;
  };

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override;

  /// If the indices to \p GEP can be traced to constants, incorporate all
  /// of these into \p UsrOI.
  ///
  /// \return true iff \p UsrOI is updated.
  bool collectConstantsForGEP(Attributor &A, const DataLayout &DL,
                              OffsetInfo &UsrOI, const OffsetInfo &PtrOI,
                              const GEPOperator *GEP);

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
  }
};

bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
                                                   const DataLayout &DL,
                                                   OffsetInfo &UsrOI,
                                                   const OffsetInfo &PtrOI,
                                                   const GEPOperator *GEP) {
  unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP->getType());
  MapVector<Value *, APInt> VariableOffsets;
  APInt ConstantOffset(BitWidth, 0);

  assert(!UsrOI.isUnknown() && !PtrOI.isUnknown() &&
         "Don't look for constant values if the offset has already been "
         "determined to be unknown.");

  if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset)) {
    UsrOI.setUnknown();
    return true;
  }

  LLVM_DEBUG(dbgs() << "[AAPointerInfo] GEP offset is "
                    << (VariableOffsets.empty() ? "" : "not") << " constant "
                    << *GEP << "\n");

  auto Union = PtrOI;
  Union.addToAll(ConstantOffset.getSExtValue());

  // Each VI in VariableOffsets has a set of potential constant values. Every
  // combination of elements, picked one each from these sets, is separately
  // added to the original set of offsets, thus resulting in more offsets.
  for (const auto &VI : VariableOffsets) {
    auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
        *this, IRPosition::value(*VI.first), DepClassTy::OPTIONAL);
    if (!PotentialConstantsAA || !PotentialConstantsAA->isValidState()) {
      UsrOI.setUnknown();
      return true;
    }

    // UndefValue is treated as a zero, which leaves Union as is.
    if (PotentialConstantsAA->undefIsContained())
      continue;

    // We need at least one constant in every set to compute an actual offset.
    // Otherwise, we end up pessimizing AAPointerInfo by respecting offsets that
    // don't actually exist. In other words, the absence of constant values
    // implies that the operation can be assumed dead for now.
    auto &AssumedSet = PotentialConstantsAA->getAssumedSet();
    if (AssumedSet.empty())
      return false;

    OffsetInfo Product;
    for (const auto &ConstOffset : AssumedSet) {
      auto CopyPerOffset = Union;
      CopyPerOffset.addToAll(ConstOffset.getSExtValue() *
                             VI.second.getZExtValue());
      Product.merge(CopyPerOffset);
    }
    Union = Product;
  }

  UsrOI = std::move(Union);
  return true;
}

ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {
  using namespace AA::PointerInfo;
  ChangeStatus Changed = ChangeStatus::UNCHANGED;
  const DataLayout &DL = A.getDataLayout();
  Value &AssociatedValue = getAssociatedValue();

  DenseMap<Value *, OffsetInfo> OffsetInfoMap;
  OffsetInfoMap[&AssociatedValue].insert(0);

  auto HandlePassthroughUser = [&](Value *Usr, Value *CurPtr, bool &Follow) {
    // One does not simply walk into a map and assign a reference to a possibly
    // new location. That can cause an invalidation before the assignment
    // happens, like so:
    //
    //   OffsetInfoMap[Usr] = OffsetInfoMap[CurPtr]; /* bad idea! */
    //
    // The RHS is a reference that may be invalidated by an insertion caused by
    // the LHS. So we ensure that the side-effect of the LHS happens first.
    auto &UsrOI = OffsetInfoMap[Usr];
    auto &PtrOI = OffsetInfoMap[CurPtr];
    assert(!PtrOI.isUnassigned() &&
           "Cannot pass through if the input Ptr was not visited!");
    UsrOI = PtrOI;
    Follow = true;
    return true;
  };

  const auto *F = getAnchorScope();
  const auto *CI =
      F ? A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(*F)
        : nullptr;
  const auto *TLI =
      F ? A.getInfoCache().getTargetLibraryInfoForFunction(*F) : nullptr;

  auto UsePred = [&](const Use &U, bool &Follow) -> bool {
    Value *CurPtr = U.get();
    User *Usr = U.getUser();
    LLVM_DEBUG(dbgs() << "[AAPointerInfo] Analyze " << *CurPtr << " in " << *Usr
                      << "\n");
    assert(OffsetInfoMap.count(CurPtr) &&
           "The current pointer offset should have been seeded!");

    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Usr)) {
      if (CE->isCast())
        return HandlePassthroughUser(Usr, CurPtr, Follow);
      if (CE->isCompare())
        return true;
      if (!isa<GEPOperator>(CE)) {
        LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled constant user " << *CE
                          << "\n");
        return false;
      }
    }
    if (auto *GEP = dyn_cast<GEPOperator>(Usr)) {
      // Note the order here, the Usr access might change the map, CurPtr is
      // already in it though.
      auto &UsrOI = OffsetInfoMap[Usr];
      auto &PtrOI = OffsetInfoMap[CurPtr];

      if (UsrOI.isUnknown())
        return true;

      if (PtrOI.isUnknown()) {
        Follow = true;
        UsrOI.setUnknown();
        return true;
      }

      Follow = collectConstantsForGEP(A, DL, UsrOI, PtrOI, GEP);
      return true;
    }
    if (isa<PtrToIntInst>(Usr))
      return false;
    if (isa<CastInst>(Usr) || isa<SelectInst>(Usr) || isa<ReturnInst>(Usr))
      return HandlePassthroughUser(Usr, CurPtr, Follow);

    // For PHIs we need to take care of the recurrence explicitly as the value
    // might change while we iterate through a loop. For now, we give up if
    // the PHI is not invariant.
    if (isa<PHINode>(Usr)) {
      // Note the order here, the Usr access might change the map, CurPtr is
      // already in it though.
      bool IsFirstPHIUser = !OffsetInfoMap.count(Usr);
      auto &UsrOI = OffsetInfoMap[Usr];
      auto &PtrOI = OffsetInfoMap[CurPtr];

      // Check if the PHI operand has already an unknown offset as we can't
      // improve on that anymore.
      if (PtrOI.isUnknown()) {
        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand offset unknown "
                          << *CurPtr << " in " << *Usr << "\n");
        Follow = !UsrOI.isUnknown();
        UsrOI.setUnknown();
        return true;
      }

      // Check if the PHI is invariant (so far).
      if (UsrOI == PtrOI) {
        assert(!PtrOI.isUnassigned() &&
               "Cannot assign if the current Ptr was not visited!");
        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant (so far)");
        return true;
      }

      // Check if the PHI operand can be traced back to AssociatedValue.
      APInt Offset(
          DL.getIndexSizeInBits(CurPtr->getType()->getPointerAddressSpace()),
          0);
      Value *CurPtrBase = CurPtr->stripAndAccumulateConstantOffsets(
          DL, Offset, /* AllowNonInbounds */ true);
      auto It = OffsetInfoMap.find(CurPtrBase);
      if (It == OffsetInfoMap.end()) {
        LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI operand is too complex "
                          << *CurPtr << " in " << *Usr << "\n");
        UsrOI.setUnknown();
        Follow = true;
        return true;
      }

      // Check if the PHI operand is not dependent on the PHI itself. Every
      // recurrence is a cyclic net of PHIs in the data flow, and has an
      // equivalent Cycle in the control flow. One of those PHIs must be in the
      // header of that control flow Cycle. This is independent of the choice of
      // Cycles reported by CycleInfo. It is sufficient to check the PHIs in
      // every Cycle header; if such a node is marked unknown, this will
      // eventually propagate through the whole net of PHIs in the recurrence.
      if (mayBeInCycle(CI, cast<Instruction>(Usr), /* HeaderOnly */ true)) {
        auto BaseOI = It->getSecond();
        BaseOI.addToAll(Offset.getZExtValue());
        if (IsFirstPHIUser || BaseOI == UsrOI) {
          LLVM_DEBUG(dbgs() << "[AAPointerInfo] PHI is invariant " << *CurPtr
                            << " in " << *Usr << "\n");
          return HandlePassthroughUser(Usr, CurPtr, Follow);
        }

        LLVM_DEBUG(
            dbgs() << "[AAPointerInfo] PHI operand pointer offset mismatch "
                   << *CurPtr << " in " << *Usr << "\n");
        UsrOI.setUnknown();
        Follow = true;
        return true;
      }

      UsrOI.merge(PtrOI);
      Follow = true;
      return true;
    }

    if (auto *LoadI = dyn_cast<LoadInst>(Usr)) {
      // If the access is to a pointer that may or may not be the associated
      // value, e.g. due to a PHI, we cannot assume it will be read.
      AccessKind AK = AccessKind::AK_R;
      if (getUnderlyingObject(CurPtr) == &AssociatedValue)
        AK = AccessKind(AK | AccessKind::AK_MUST);
      else
        AK = AccessKind(AK | AccessKind::AK_MAY);
      if (!handleAccess(A, *LoadI, /* Content */ nullptr, AK,
                        OffsetInfoMap[CurPtr].Offsets, Changed,
                        *LoadI->getType()))
        return false;

      auto IsAssumption = [](Instruction &I) {
        if (auto *II = dyn_cast<IntrinsicInst>(&I))
          return II->isAssumeLikeIntrinsic();
        return false;
      };

      auto IsImpactedInRange = [&](Instruction *FromI, Instruction *ToI) {
        // Check if the assumption and the load are executed together without
        // memory modification.
        do {
          if (FromI->mayWriteToMemory() && !IsAssumption(*FromI))
            return true;
          FromI = FromI->getNextNonDebugInstruction();
        } while (FromI && FromI != ToI);
        return false;
      };

      BasicBlock *BB = LoadI->getParent();
      auto IsValidAssume = [&](IntrinsicInst &IntrI) {
        if (IntrI.getIntrinsicID() != Intrinsic::assume)
          return false;
        BasicBlock *IntrBB = IntrI.getParent();
        if (IntrI.getParent() == BB) {
          if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(), &IntrI))
            return false;
        } else {
          auto PredIt = pred_begin(IntrBB);
          if (PredIt == pred_end(IntrBB))
            return false;
          if ((*PredIt) != BB)
            return false;
          if (++PredIt != pred_end(IntrBB))
            return false;
          for (auto *SuccBB : successors(BB)) {
            if (SuccBB == IntrBB)
              continue;
            if (isa<UnreachableInst>(SuccBB->getTerminator()))
              continue;
            return false;
          }
          if (IsImpactedInRange(LoadI->getNextNonDebugInstruction(),
                                BB->getTerminator()))
            return false;
          if (IsImpactedInRange(&IntrBB->front(), &IntrI))
            return false;
        }
        return true;
      };

      std::pair<Value *, IntrinsicInst *> Assumption;
      for (const Use &LoadU : LoadI->uses()) {
        if (auto *CmpI = dyn_cast<CmpInst>(LoadU.getUser())) {
          if (!CmpI->isEquality() || !CmpI->isTrueWhenEqual())
            continue;
          for (const Use &CmpU : CmpI->uses()) {
            if (auto *IntrI = dyn_cast<IntrinsicInst>(CmpU.getUser())) {
              if (!IsValidAssume(*IntrI))
                continue;
              int Idx = CmpI->getOperandUse(0) == LoadU;
              Assumption = {CmpI->getOperand(Idx), IntrI};
              break;
            }
          }
        }
        if (Assumption.first)
          break;
      }

      // Check if we found an assumption associated with this load.
      if (!Assumption.first || !Assumption.second)
        return true;

      LLVM_DEBUG(dbgs() << "[AAPointerInfo] Assumption found "
                        << *Assumption.second << ": " << *LoadI
                        << " == " << *Assumption.first << "\n");

      return handleAccess(
          A, *Assumption.second, Assumption.first, AccessKind::AK_ASSUMPTION,
          OffsetInfoMap[CurPtr].Offsets, Changed, *LoadI->getType());
    }

    auto HandleStoreLike = [&](Instruction &I, Value *ValueOp, Type &ValueTy,
                               ArrayRef<Value *> OtherOps, AccessKind AK) {
      for (auto *OtherOp : OtherOps) {
        if (OtherOp == CurPtr) {
          LLVM_DEBUG(
              dbgs()
              << "[AAPointerInfo] Escaping use in store like instruction " << I
              << "\n");
          return false;
        }
      }

      // If the access is to a pointer that may or may not be the associated
      // value, e.g. due to a PHI, we cannot assume it will be written.
      if (getUnderlyingObject(CurPtr) == &AssociatedValue)
        AK = AccessKind(AK | AccessKind::AK_MUST);
      else
        AK = AccessKind(AK | AccessKind::AK_MAY);
      bool UsedAssumedInformation = false;
      std::optional<Value *> Content = nullptr;
      if (ValueOp)
        Content = A.getAssumedSimplified(
            *ValueOp, *this, UsedAssumedInformation, AA::Interprocedural);
      return handleAccess(A, I, Content, AK, OffsetInfoMap[CurPtr].Offsets,
                          Changed, ValueTy);
    };

    if (auto *StoreI = dyn_cast<StoreInst>(Usr))
      return HandleStoreLike(*StoreI, StoreI->getValueOperand(),
                             *StoreI->getValueOperand()->getType(),
                             {StoreI->getValueOperand()}, AccessKind::AK_W);
    if (auto *RMWI = dyn_cast<AtomicRMWInst>(Usr))
      return HandleStoreLike(*RMWI, nullptr, *RMWI->getValOperand()->getType(),
                             {RMWI->getValOperand()}, AccessKind::AK_RW);
    if (auto *CXI = dyn_cast<AtomicCmpXchgInst>(Usr))
      return HandleStoreLike(
          *CXI, nullptr, *CXI->getNewValOperand()->getType(),
          {CXI->getCompareOperand(), CXI->getNewValOperand()},
          AccessKind::AK_RW);

    if (auto *CB = dyn_cast<CallBase>(Usr)) {
      if (CB->isLifetimeStartOrEnd())
        return true;
      if (getFreedOperand(CB, TLI) == U)
        return true;
      if (CB->isArgOperand(&U)) {
        unsigned ArgNo = CB->getArgOperandNo(&U);
        const auto *CSArgPI = A.getAAFor<AAPointerInfo>(
            *this, IRPosition::callsite_argument(*CB, ArgNo),
            DepClassTy::REQUIRED);
        if (!CSArgPI)
          return false;
        Changed =
            translateAndAddState(A, *CSArgPI, OffsetInfoMap[CurPtr], *CB) |
            Changed;
        return isValidState();
      }
      LLVM_DEBUG(dbgs() << "[AAPointerInfo] Call user not handled " << *CB
                        << "\n");
      // TODO: Allow some call uses
      return false;
    }

    LLVM_DEBUG(dbgs() << "[AAPointerInfo] User not handled " << *Usr << "\n");
    return false;
  };
  auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
    assert(OffsetInfoMap.count(OldU) && "Old use should be known already!");
    if (OffsetInfoMap.count(NewU)) {
      LLVM_DEBUG({
        if (!(OffsetInfoMap[NewU] == OffsetInfoMap[OldU])) {
          dbgs() << "[AAPointerInfo] Equivalent use callback failed: "
                 << OffsetInfoMap[NewU] << " vs " << OffsetInfoMap[OldU]
                 << "\n";
        }
      });
      return OffsetInfoMap[NewU] == OffsetInfoMap[OldU];
    }
    OffsetInfoMap[NewU] = OffsetInfoMap[OldU];
    return true;
  };
  if (!A.checkForAllUses(UsePred, *this, AssociatedValue,
                         /* CheckBBLivenessOnly */ true, DepClassTy::OPTIONAL,
                         /* IgnoreDroppableUses */ true, EquivalentUseCB)) {
    LLVM_DEBUG(dbgs() << "[AAPointerInfo] Check for all uses failed, abort!\n");
    return indicatePessimisticFixpoint();
  }

  LLVM_DEBUG({
    dbgs() << "Accesses by bin after update:\n";
    dumpState(dbgs());
  });

  return Changed;
}

struct AAPointerInfoReturned final : AAPointerInfoImpl {
  AAPointerInfoReturned(const IRPosition &IRP, Attributor &A)
      : AAPointerInfoImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
  }
};

struct AAPointerInfoArgument final : AAPointerInfoFloating {
  AAPointerInfoArgument(const IRPosition &IRP, Attributor &A)
      : AAPointerInfoFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
  }
};

struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {
  AAPointerInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAPointerInfoFloating(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    using namespace AA::PointerInfo;
    // We handle memory intrinsics explicitly, at least the first (=
    // destination) and second (=source) arguments as we know how they are
    // accessed.
    if (auto *MI = dyn_cast_or_null<MemIntrinsic>(getCtxI())) {
      ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
      int64_t LengthVal = AA::RangeTy::Unknown;
      if (Length)
        LengthVal = Length->getSExtValue();
      unsigned ArgNo = getIRPosition().getCallSiteArgNo();
      ChangeStatus Changed = ChangeStatus::UNCHANGED;
      if (ArgNo > 1) {
        LLVM_DEBUG(dbgs() << "[AAPointerInfo] Unhandled memory intrinsic "
                          << *MI << "\n");
        return indicatePessimisticFixpoint();
      } else {
        auto Kind =
            ArgNo == 0 ? AccessKind::AK_MUST_WRITE : AccessKind::AK_MUST_READ;
        Changed =
            Changed | addAccess(A, {0, LengthVal}, *MI, nullptr, Kind, nullptr);
      }
      LLVM_DEBUG({
        dbgs() << "Accesses by bin after update:\n";
        dumpState(dbgs());
      });

      return Changed;
    }

    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    if (Arg) {
      const IRPosition &ArgPos = IRPosition::argument(*Arg);
      auto *ArgAA =
          A.getAAFor<AAPointerInfo>(*this, ArgPos, DepClassTy::REQUIRED);
      if (ArgAA && ArgAA->getState().isValidState())
        return translateAndAddStateFromCallee(A, *ArgAA,
                                              *cast<CallBase>(getCtxI()));
      if (!Arg->getParent()->isDeclaration())
        return indicatePessimisticFixpoint();
    }

    bool IsKnownNoCapture;
    if (!AA::hasAssumedIRAttr<Attribute::NoCapture>(
            A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoCapture))
      return indicatePessimisticFixpoint();

    bool IsKnown = false;
    if (AA::isAssumedReadNone(A, getIRPosition(), *this, IsKnown))
      return ChangeStatus::UNCHANGED;
    bool ReadOnly = AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown);
    auto Kind =
        ReadOnly ? AccessKind::AK_MAY_READ : AccessKind::AK_MAY_READ_WRITE;
    return addAccess(A, AA::RangeTy::getUnknown(), *getCtxI(), nullptr, Kind,
                     nullptr);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
  }
};

struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {
  AAPointerInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAPointerInfoFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    AAPointerInfoImpl::trackPointerInfoStatistics(getIRPosition());
  }
};
} // namespace

/// -----------------------NoUnwind Function Attribute--------------------------

namespace {
struct AANoUnwindImpl : AANoUnwind {
  AANoUnwindImpl(const IRPosition &IRP, Attributor &A) : AANoUnwind(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoUnwind>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "nounwind" : "may-unwind";
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto Opcodes = {
        (unsigned)Instruction::Invoke,      (unsigned)Instruction::CallBr,
        (unsigned)Instruction::Call,        (unsigned)Instruction::CleanupRet,
        (unsigned)Instruction::CatchSwitch, (unsigned)Instruction::Resume};

    auto CheckForNoUnwind = [&](Instruction &I) {
      if (!I.mayThrow(/* IncludePhaseOneUnwind */ true))
        return true;

      if (const auto *CB = dyn_cast<CallBase>(&I)) {
        bool IsKnownNoUnwind;
        return AA::hasAssumedIRAttr<Attribute::NoUnwind>(
            A, this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED,
            IsKnownNoUnwind);
      }
      return false;
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllInstructions(CheckForNoUnwind, *this, Opcodes,
                                   UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }
};

struct AANoUnwindFunction final : public AANoUnwindImpl {
  AANoUnwindFunction(const IRPosition &IRP, Attributor &A)
      : AANoUnwindImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nounwind) }
};

/// NoUnwind attribute deduction for a call sites.
struct AANoUnwindCallSite final : AANoUnwindImpl {
  AANoUnwindCallSite(const IRPosition &IRP, Attributor &A)
      : AANoUnwindImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnownNoUnwind;
    if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownNoUnwind))
      return ChangeStatus::UNCHANGED;
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nounwind); }
};
} // namespace

/// ------------------------ NoSync Function Attribute -------------------------

bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {
  switch (CB.getIntrinsicID()) {
  case Intrinsic::nvvm_barrier0:
  case Intrinsic::nvvm_barrier0_and:
  case Intrinsic::nvvm_barrier0_or:
  case Intrinsic::nvvm_barrier0_popc:
    return true;
  case Intrinsic::amdgcn_s_barrier:
    if (ExecutedAligned)
      return true;
    break;
  default:
    break;
  }
  return hasAssumption(CB, KnownAssumptionString("ompx_aligned_barrier"));
}

bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {
  if (!I->isAtomic())
    return false;

  if (auto *FI = dyn_cast<FenceInst>(I))
    // All legal orderings for fence are stronger than monotonic.
    return FI->getSyncScopeID() != SyncScope::SingleThread;
  if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
    // Unordered is not a legal ordering for cmpxchg.
    return (AI->getSuccessOrdering() != AtomicOrdering::Monotonic ||
            AI->getFailureOrdering() != AtomicOrdering::Monotonic);
  }

  AtomicOrdering Ordering;
  switch (I->getOpcode()) {
  case Instruction::AtomicRMW:
    Ordering = cast<AtomicRMWInst>(I)->getOrdering();
    break;
  case Instruction::Store:
    Ordering = cast<StoreInst>(I)->getOrdering();
    break;
  case Instruction::Load:
    Ordering = cast<LoadInst>(I)->getOrdering();
    break;
  default:
    llvm_unreachable(
        "New atomic operations need to be known in the attributor.");
  }

  return (Ordering != AtomicOrdering::Unordered &&
          Ordering != AtomicOrdering::Monotonic);
}

/// Return true if this intrinsic is nosync.  This is only used for intrinsics
/// which would be nosync except that they have a volatile flag.  All other
/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {
  if (auto *MI = dyn_cast<MemIntrinsic>(I))
    return !MI->isVolatile();
  return false;
}

namespace {
struct AANoSyncImpl : AANoSync {
  AANoSyncImpl(const IRPosition &IRP, Attributor &A) : AANoSync(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoSync>(A, nullptr, getIRPosition(),
                                                    DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "nosync" : "may-sync";
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override;
};

ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {

  auto CheckRWInstForNoSync = [&](Instruction &I) {
    return AA::isNoSyncInst(A, I, *this);
  };

  auto CheckForNoSync = [&](Instruction &I) {
    // At this point we handled all read/write effects and they are all
    // nosync, so they can be skipped.
    if (I.mayReadOrWriteMemory())
      return true;

    // non-convergent and readnone imply nosync.
    return !cast<CallBase>(I).isConvergent();
  };

  bool UsedAssumedInformation = false;
  if (!A.checkForAllReadWriteInstructions(CheckRWInstForNoSync, *this,
                                          UsedAssumedInformation) ||
      !A.checkForAllCallLikeInstructions(CheckForNoSync, *this,
                                         UsedAssumedInformation))
    return indicatePessimisticFixpoint();

  return ChangeStatus::UNCHANGED;
}

struct AANoSyncFunction final : public AANoSyncImpl {
  AANoSyncFunction(const IRPosition &IRP, Attributor &A)
      : AANoSyncImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nosync) }
};

/// NoSync attribute deduction for a call sites.
struct AANoSyncCallSite final : AANoSyncImpl {
  AANoSyncCallSite(const IRPosition &IRP, Attributor &A)
      : AANoSyncImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnownNoSycn;
    if (AA::hasAssumedIRAttr<Attribute::NoSync>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownNoSycn))
      return ChangeStatus::UNCHANGED;
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nosync); }
};
} // namespace

/// ------------------------ No-Free Attributes ----------------------------

namespace {
struct AANoFreeImpl : public AANoFree {
  AANoFreeImpl(const IRPosition &IRP, Attributor &A) : AANoFree(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoFree>(A, nullptr, getIRPosition(),
                                                    DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto CheckForNoFree = [&](Instruction &I) {
      bool IsKnown;
      return AA::hasAssumedIRAttr<Attribute::NoFree>(
          A, this, IRPosition::callsite_function(cast<CallBase>(I)),
          DepClassTy::REQUIRED, IsKnown);
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallLikeInstructions(CheckForNoFree, *this,
                                           UsedAssumedInformation))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "nofree" : "may-free";
  }
};

struct AANoFreeFunction final : public AANoFreeImpl {
  AANoFreeFunction(const IRPosition &IRP, Attributor &A)
      : AANoFreeImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(nofree) }
};

/// NoFree attribute deduction for a call sites.
struct AANoFreeCallSite final : AANoFreeImpl {
  AANoFreeCallSite(const IRPosition &IRP, Attributor &A)
      : AANoFreeImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnown;
    if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, this, FnPos,
                                                DepClassTy::REQUIRED, IsKnown))
      return ChangeStatus::UNCHANGED;
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(nofree); }
};

/// NoFree attribute for floating values.
struct AANoFreeFloating : AANoFreeImpl {
  AANoFreeFloating(const IRPosition &IRP, Attributor &A)
      : AANoFreeImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override{STATS_DECLTRACK_FLOATING_ATTR(nofree)}

  /// See Abstract Attribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    const IRPosition &IRP = getIRPosition();

    bool IsKnown;
    if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, this,
                                                IRPosition::function_scope(IRP),
                                                DepClassTy::OPTIONAL, IsKnown))
      return ChangeStatus::UNCHANGED;

    Value &AssociatedValue = getIRPosition().getAssociatedValue();
    auto Pred = [&](const Use &U, bool &Follow) -> bool {
      Instruction *UserI = cast<Instruction>(U.getUser());
      if (auto *CB = dyn_cast<CallBase>(UserI)) {
        if (CB->isBundleOperand(&U))
          return false;
        if (!CB->isArgOperand(&U))
          return true;
        unsigned ArgNo = CB->getArgOperandNo(&U);

        bool IsKnown;
        return AA::hasAssumedIRAttr<Attribute::NoFree>(
            A, this, IRPosition::callsite_argument(*CB, ArgNo),
            DepClassTy::REQUIRED, IsKnown);
      }

      if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
          isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
        Follow = true;
        return true;
      }
      if (isa<StoreInst>(UserI) || isa<LoadInst>(UserI) ||
          isa<ReturnInst>(UserI))
        return true;

      // Unknown user.
      return false;
    };
    if (!A.checkForAllUses(Pred, *this, AssociatedValue))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }
};

/// NoFree attribute for a call site argument.
struct AANoFreeArgument final : AANoFreeFloating {
  AANoFreeArgument(const IRPosition &IRP, Attributor &A)
      : AANoFreeFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofree) }
};

/// NoFree attribute for call site arguments.
struct AANoFreeCallSiteArgument final : AANoFreeFloating {
  AANoFreeCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANoFreeFloating(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    if (!Arg)
      return indicatePessimisticFixpoint();
    const IRPosition &ArgPos = IRPosition::argument(*Arg);
    bool IsKnown;
    if (AA::hasAssumedIRAttr<Attribute::NoFree>(A, this, ArgPos,
                                                DepClassTy::REQUIRED, IsKnown))
      return ChangeStatus::UNCHANGED;
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nofree)};
};

/// NoFree attribute for function return value.
struct AANoFreeReturned final : AANoFreeFloating {
  AANoFreeReturned(const IRPosition &IRP, Attributor &A)
      : AANoFreeFloating(IRP, A) {
    llvm_unreachable("NoFree is not applicable to function returns!");
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    llvm_unreachable("NoFree is not applicable to function returns!");
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("NoFree is not applicable to function returns!");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}
};

/// NoFree attribute deduction for a call site return value.
struct AANoFreeCallSiteReturned final : AANoFreeFloating {
  AANoFreeCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AANoFreeFloating(IRP, A) {}

  ChangeStatus manifest(Attributor &A) override {
    return ChangeStatus::UNCHANGED;
  }
  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nofree) }
};
} // namespace

/// ------------------------ NonNull Argument Attribute ------------------------

bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {
  SmallVector<Attribute::AttrKind, 2> AttrKinds;
  AttrKinds.push_back(Attribute::NonNull);
  if (!NullPointerIsDefined(IRP.getAnchorScope(),
                            IRP.getAssociatedType()->getPointerAddressSpace()))
    AttrKinds.push_back(Attribute::Dereferenceable);
  if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull))
    return true;

  if (IRP.getPositionKind() == IRP_RETURNED)
    return false;

  DominatorTree *DT = nullptr;
  AssumptionCache *AC = nullptr;
  InformationCache &InfoCache = A.getInfoCache();
  if (const Function *Fn = IRP.getAnchorScope()) {
    if (!Fn->isDeclaration()) {
      DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*Fn);
      AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*Fn);
    }
  }

  if (!isKnownNonZero(&IRP.getAssociatedValue(), A.getDataLayout(), 0, AC,
                      IRP.getCtxI(), DT))
    return false;
  A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
                                       Attribute::NonNull)});
  return true;
}

namespace {
static int64_t getKnownNonNullAndDerefBytesForUse(
    Attributor &A, const AbstractAttribute &QueryingAA, Value &AssociatedValue,
    const Use *U, const Instruction *I, bool &IsNonNull, bool &TrackUse) {
  TrackUse = false;

  const Value *UseV = U->get();
  if (!UseV->getType()->isPointerTy())
    return 0;

  // We need to follow common pointer manipulation uses to the accesses they
  // feed into. We can try to be smart to avoid looking through things we do not
  // like for now, e.g., non-inbounds GEPs.
  if (isa<CastInst>(I)) {
    TrackUse = true;
    return 0;
  }

  if (isa<GetElementPtrInst>(I)) {
    TrackUse = true;
    return 0;
  }

  Type *PtrTy = UseV->getType();
  const Function *F = I->getFunction();
  bool NullPointerIsDefined =
      F ? llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()) : true;
  const DataLayout &DL = A.getInfoCache().getDL();
  if (const auto *CB = dyn_cast<CallBase>(I)) {
    if (CB->isBundleOperand(U)) {
      if (RetainedKnowledge RK = getKnowledgeFromUse(
              U, {Attribute::NonNull, Attribute::Dereferenceable})) {
        IsNonNull |=
            (RK.AttrKind == Attribute::NonNull || !NullPointerIsDefined);
        return RK.ArgValue;
      }
      return 0;
    }

    if (CB->isCallee(U)) {
      IsNonNull |= !NullPointerIsDefined;
      return 0;
    }

    unsigned ArgNo = CB->getArgOperandNo(U);
    IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
    // As long as we only use known information there is no need to track
    // dependences here.
    bool IsKnownNonNull;
    AA::hasAssumedIRAttr<Attribute::NonNull>(A, &QueryingAA, IRP,
                                             DepClassTy::NONE, IsKnownNonNull);
    IsNonNull |= IsKnownNonNull;
    auto *DerefAA =
        A.getAAFor<AADereferenceable>(QueryingAA, IRP, DepClassTy::NONE);
    return DerefAA ? DerefAA->getKnownDereferenceableBytes() : 0;
  }

  std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
  if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
    return 0;

  int64_t Offset;
  const Value *Base =
      getMinimalBaseOfPointer(A, QueryingAA, Loc->Ptr, Offset, DL);
  if (Base && Base == &AssociatedValue) {
    int64_t DerefBytes = Loc->Size.getValue() + Offset;
    IsNonNull |= !NullPointerIsDefined;
    return std::max(int64_t(0), DerefBytes);
  }

  /// Corner case when an offset is 0.
  Base = GetPointerBaseWithConstantOffset(Loc->Ptr, Offset, DL,
                                          /*AllowNonInbounds*/ true);
  if (Base && Base == &AssociatedValue && Offset == 0) {
    int64_t DerefBytes = Loc->Size.getValue();
    IsNonNull |= !NullPointerIsDefined;
    return std::max(int64_t(0), DerefBytes);
  }

  return 0;
}

struct AANonNullImpl : AANonNull {
  AANonNullImpl(const IRPosition &IRP, Attributor &A) : AANonNull(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    Value &V = *getAssociatedValue().stripPointerCasts();
    if (isa<ConstantPointerNull>(V)) {
      indicatePessimisticFixpoint();
      return;
    }

    if (Instruction *CtxI = getCtxI())
      followUsesInMBEC(*this, A, getState(), *CtxI);
  }

  /// See followUsesInMBEC
  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
                       AANonNull::StateType &State) {
    bool IsNonNull = false;
    bool TrackUse = false;
    getKnownNonNullAndDerefBytesForUse(A, *this, getAssociatedValue(), U, I,
                                       IsNonNull, TrackUse);
    State.setKnown(IsNonNull);
    return TrackUse;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "nonnull" : "may-null";
  }
};

/// NonNull attribute for a floating value.
struct AANonNullFloating : public AANonNullImpl {
  AANonNullFloating(const IRPosition &IRP, Attributor &A)
      : AANonNullImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto CheckIRP = [&](const IRPosition &IRP) {
      bool IsKnownNonNull;
      return AA::hasAssumedIRAttr<Attribute::NonNull>(
          A, *this, IRP, DepClassTy::OPTIONAL, IsKnownNonNull);
    };

    bool Stripped;
    bool UsedAssumedInformation = false;
    Value *AssociatedValue = &getAssociatedValue();
    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
                                      AA::AnyScope, UsedAssumedInformation))
      Stripped = false;
    else
      Stripped =
          Values.size() != 1 || Values.front().getValue() != AssociatedValue;

    if (!Stripped) {
      // If we haven't stripped anything we might still be able to use a
      // different AA, but only if the IRP changes. Effectively when we
      // interpret this not as a call site value but as a floating/argument
      // value.
      const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
      if (AVIRP == getIRPosition() || !CheckIRP(AVIRP))
        return indicatePessimisticFixpoint();
      return ChangeStatus::UNCHANGED;
    }

    for (const auto &VAC : Values)
      if (!CheckIRP(IRPosition::value(*VAC.getValue())))
        return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
};

/// NonNull attribute for function return value.
struct AANonNullReturned final
    : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
                                   false, AANonNull::IRAttributeKind> {
  AANonNullReturned(const IRPosition &IRP, Attributor &A)
      : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
                                     false, Attribute::NonNull>(IRP, A) {}

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "nonnull" : "may-null";
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(nonnull) }
};

/// NonNull attribute for function argument.
struct AANonNullArgument final
    : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl,
                                      AANonNull::StateType, false,
                                      AANonNull::IRAttributeKind> {
  AANonNullArgument(const IRPosition &IRP, Attributor &A)
      : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl,
                                        AANonNull::StateType, false,
                                        AANonNull::IRAttributeKind>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nonnull) }
};

struct AANonNullCallSiteArgument final : AANonNullFloating {
  AANonNullCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANonNullFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(nonnull) }
};

/// NonNull attribute for a call site return position.
struct AANonNullCallSiteReturned final
    : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl,
                                     AANonNull::StateType, false,
                                     AANonNull::IRAttributeKind> {
  AANonNullCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AACallSiteReturnedFromReturned<AANonNull, AANonNullImpl,
                                       AANonNull::StateType, false,
                                       AANonNull::IRAttributeKind>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(nonnull) }
};
} // namespace

/// ------------------------ Must-Progress Attributes --------------------------
namespace {
struct AAMustProgressImpl : public AAMustProgress {
  AAMustProgressImpl(const IRPosition &IRP, Attributor &A)
      : AAMustProgress(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::MustProgress>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "mustprogress" : "may-not-progress";
  }
};

struct AAMustProgressFunction final : AAMustProgressImpl {
  AAMustProgressFunction(const IRPosition &IRP, Attributor &A)
      : AAMustProgressImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    bool IsKnown;
    if (AA::hasAssumedIRAttr<Attribute::WillReturn>(
            A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnown)) {
      if (IsKnown)
        return indicateOptimisticFixpoint();
      return ChangeStatus::UNCHANGED;
    }

    auto CheckForMustProgress = [&](AbstractCallSite ACS) {
      IRPosition IPos = IRPosition::callsite_function(*ACS.getInstruction());
      bool IsKnownMustProgress;
      return AA::hasAssumedIRAttr<Attribute::MustProgress>(
          A, this, IPos, DepClassTy::REQUIRED, IsKnownMustProgress,
          /* IgnoreSubsumingPositions */ true);
    };

    bool AllCallSitesKnown = true;
    if (!A.checkForAllCallSites(CheckForMustProgress, *this,
                                /* RequireAllCallSites */ true,
                                AllCallSitesKnown))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FN_ATTR(mustprogress)
  }
};

/// MustProgress attribute deduction for a call sites.
struct AAMustProgressCallSite final : AAMustProgressImpl {
  AAMustProgressCallSite(const IRPosition &IRP, Attributor &A)
      : AAMustProgressImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
    bool IsKnownMustProgress;
    if (!AA::hasAssumedIRAttr<Attribute::MustProgress>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownMustProgress))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CS_ATTR(mustprogress);
  }
};
} // namespace

/// ------------------------ No-Recurse Attributes ----------------------------

namespace {
struct AANoRecurseImpl : public AANoRecurse {
  AANoRecurseImpl(const IRPosition &IRP, Attributor &A) : AANoRecurse(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoRecurse>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "norecurse" : "may-recurse";
  }
};

struct AANoRecurseFunction final : AANoRecurseImpl {
  AANoRecurseFunction(const IRPosition &IRP, Attributor &A)
      : AANoRecurseImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {

    // If all live call sites are known to be no-recurse, we are as well.
    auto CallSitePred = [&](AbstractCallSite ACS) {
      bool IsKnownNoRecurse;
      if (!AA::hasAssumedIRAttr<Attribute::NoRecurse>(
              A, this,
              IRPosition::function(*ACS.getInstruction()->getFunction()),
              DepClassTy::NONE, IsKnownNoRecurse))
        return false;
      return IsKnownNoRecurse;
    };
    bool UsedAssumedInformation = false;
    if (A.checkForAllCallSites(CallSitePred, *this, true,
                               UsedAssumedInformation)) {
      // If we know all call sites and all are known no-recurse, we are done.
      // If all known call sites, which might not be all that exist, are known
      // to be no-recurse, we are not done but we can continue to assume
      // no-recurse. If one of the call sites we have not visited will become
      // live, another update is triggered.
      if (!UsedAssumedInformation)
        indicateOptimisticFixpoint();
      return ChangeStatus::UNCHANGED;
    }

    const AAInterFnReachability *EdgeReachability =
        A.getAAFor<AAInterFnReachability>(*this, getIRPosition(),
                                          DepClassTy::REQUIRED);
    if (EdgeReachability && EdgeReachability->canReach(A, *getAnchorScope()))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(norecurse) }
};

/// NoRecurse attribute deduction for a call sites.
struct AANoRecurseCallSite final : AANoRecurseImpl {
  AANoRecurseCallSite(const IRPosition &IRP, Attributor &A)
      : AANoRecurseImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnownNoRecurse;
    if (!AA::hasAssumedIRAttr<Attribute::NoRecurse>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownNoRecurse))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(norecurse); }
};
} // namespace

/// ------------------------ No-Convergent Attribute --------------------------

namespace {
struct AANonConvergentImpl : public AANonConvergent {
  AANonConvergentImpl(const IRPosition &IRP, Attributor &A)
      : AANonConvergent(IRP, A) {}

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "non-convergent" : "may-be-convergent";
  }
};

struct AANonConvergentFunction final : AANonConvergentImpl {
  AANonConvergentFunction(const IRPosition &IRP, Attributor &A)
      : AANonConvergentImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // If all function calls are known to not be convergent, we are not
    // convergent.
    auto CalleeIsNotConvergent = [&](Instruction &Inst) {
      CallBase &CB = cast<CallBase>(Inst);
      auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
      if (!Callee || Callee->isIntrinsic()) {
        return false;
      }
      if (Callee->isDeclaration()) {
        return !Callee->hasFnAttribute(Attribute::Convergent);
      }
      const auto *ConvergentAA = A.getAAFor<AANonConvergent>(
          *this, IRPosition::function(*Callee), DepClassTy::REQUIRED);
      return ConvergentAA && ConvergentAA->isAssumedNotConvergent();
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallLikeInstructions(CalleeIsNotConvergent, *this,
                                           UsedAssumedInformation)) {
      return indicatePessimisticFixpoint();
    }
    return ChangeStatus::UNCHANGED;
  }

  ChangeStatus manifest(Attributor &A) override {
    if (isKnownNotConvergent() &&
        A.hasAttr(getIRPosition(), Attribute::Convergent)) {
      A.removeAttrs(getIRPosition(), {Attribute::Convergent});
      return ChangeStatus::CHANGED;
    }
    return ChangeStatus::UNCHANGED;
  }

  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(convergent) }
};
} // namespace

/// -------------------- Undefined-Behavior Attributes ------------------------

namespace {
struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {
  AAUndefinedBehaviorImpl(const IRPosition &IRP, Attributor &A)
      : AAUndefinedBehavior(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  // through a pointer (i.e. also branches etc.)
  ChangeStatus updateImpl(Attributor &A) override {
    const size_t UBPrevSize = KnownUBInsts.size();
    const size_t NoUBPrevSize = AssumedNoUBInsts.size();

    auto InspectMemAccessInstForUB = [&](Instruction &I) {
      // Lang ref now states volatile store is not UB, let's skip them.
      if (I.isVolatile() && I.mayWriteToMemory())
        return true;

      // Skip instructions that are already saved.
      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
        return true;

      // If we reach here, we know we have an instruction
      // that accesses memory through a pointer operand,
      // for which getPointerOperand() should give it to us.
      Value *PtrOp =
          const_cast<Value *>(getPointerOperand(&I, /* AllowVolatile */ true));
      assert(PtrOp &&
             "Expected pointer operand of memory accessing instruction");

      // Either we stopped and the appropriate action was taken,
      // or we got back a simplified value to continue.
      std::optional<Value *> SimplifiedPtrOp =
          stopOnUndefOrAssumed(A, PtrOp, &I);
      if (!SimplifiedPtrOp || !*SimplifiedPtrOp)
        return true;
      const Value *PtrOpVal = *SimplifiedPtrOp;

      // A memory access through a pointer is considered UB
      // only if the pointer has constant null value.
      // TODO: Expand it to not only check constant values.
      if (!isa<ConstantPointerNull>(PtrOpVal)) {
        AssumedNoUBInsts.insert(&I);
        return true;
      }
      const Type *PtrTy = PtrOpVal->getType();

      // Because we only consider instructions inside functions,
      // assume that a parent function exists.
      const Function *F = I.getFunction();

      // A memory access using constant null pointer is only considered UB
      // if null pointer is _not_ defined for the target platform.
      if (llvm::NullPointerIsDefined(F, PtrTy->getPointerAddressSpace()))
        AssumedNoUBInsts.insert(&I);
      else
        KnownUBInsts.insert(&I);
      return true;
    };

    auto InspectBrInstForUB = [&](Instruction &I) {
      // A conditional branch instruction is considered UB if it has `undef`
      // condition.

      // Skip instructions that are already saved.
      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
        return true;

      // We know we have a branch instruction.
      auto *BrInst = cast<BranchInst>(&I);

      // Unconditional branches are never considered UB.
      if (BrInst->isUnconditional())
        return true;

      // Either we stopped and the appropriate action was taken,
      // or we got back a simplified value to continue.
      std::optional<Value *> SimplifiedCond =
          stopOnUndefOrAssumed(A, BrInst->getCondition(), BrInst);
      if (!SimplifiedCond || !*SimplifiedCond)
        return true;
      AssumedNoUBInsts.insert(&I);
      return true;
    };

    auto InspectCallSiteForUB = [&](Instruction &I) {
      // Check whether a callsite always cause UB or not

      // Skip instructions that are already saved.
      if (AssumedNoUBInsts.count(&I) || KnownUBInsts.count(&I))
        return true;

      // Check nonnull and noundef argument attribute violation for each
      // callsite.
      CallBase &CB = cast<CallBase>(I);
      auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
      if (!Callee)
        return true;
      for (unsigned idx = 0; idx < CB.arg_size(); idx++) {
        // If current argument is known to be simplified to null pointer and the
        // corresponding argument position is known to have nonnull attribute,
        // the argument is poison. Furthermore, if the argument is poison and
        // the position is known to have noundef attriubte, this callsite is
        // considered UB.
        if (idx >= Callee->arg_size())
          break;
        Value *ArgVal = CB.getArgOperand(idx);
        if (!ArgVal)
          continue;
        // Here, we handle three cases.
        //   (1) Not having a value means it is dead. (we can replace the value
        //       with undef)
        //   (2) Simplified to undef. The argument violate noundef attriubte.
        //   (3) Simplified to null pointer where known to be nonnull.
        //       The argument is a poison value and violate noundef attribute.
        IRPosition CalleeArgumentIRP = IRPosition::callsite_argument(CB, idx);
        bool IsKnownNoUndef;
        AA::hasAssumedIRAttr<Attribute::NoUndef>(
            A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNoUndef);
        if (!IsKnownNoUndef)
          continue;
        bool UsedAssumedInformation = false;
        std::optional<Value *> SimplifiedVal =
            A.getAssumedSimplified(IRPosition::value(*ArgVal), *this,
                                   UsedAssumedInformation, AA::Interprocedural);
        if (UsedAssumedInformation)
          continue;
        if (SimplifiedVal && !*SimplifiedVal)
          return true;
        if (!SimplifiedVal || isa<UndefValue>(**SimplifiedVal)) {
          KnownUBInsts.insert(&I);
          continue;
        }
        if (!ArgVal->getType()->isPointerTy() ||
            !isa<ConstantPointerNull>(**SimplifiedVal))
          continue;
        bool IsKnownNonNull;
        AA::hasAssumedIRAttr<Attribute::NonNull>(
            A, this, CalleeArgumentIRP, DepClassTy::NONE, IsKnownNonNull);
        if (IsKnownNonNull)
          KnownUBInsts.insert(&I);
      }
      return true;
    };

    auto InspectReturnInstForUB = [&](Instruction &I) {
      auto &RI = cast<ReturnInst>(I);
      // Either we stopped and the appropriate action was taken,
      // or we got back a simplified return value to continue.
      std::optional<Value *> SimplifiedRetValue =
          stopOnUndefOrAssumed(A, RI.getReturnValue(), &I);
      if (!SimplifiedRetValue || !*SimplifiedRetValue)
        return true;

      // Check if a return instruction always cause UB or not
      // Note: It is guaranteed that the returned position of the anchor
      //       scope has noundef attribute when this is called.
      //       We also ensure the return position is not "assumed dead"
      //       because the returned value was then potentially simplified to
      //       `undef` in AAReturnedValues without removing the `noundef`
      //       attribute yet.

      // When the returned position has noundef attriubte, UB occurs in the
      // following cases.
      //   (1) Returned value is known to be undef.
      //   (2) The value is known to be a null pointer and the returned
      //       position has nonnull attribute (because the returned value is
      //       poison).
      if (isa<ConstantPointerNull>(*SimplifiedRetValue)) {
        bool IsKnownNonNull;
        AA::hasAssumedIRAttr<Attribute::NonNull>(
            A, this, IRPosition::returned(*getAnchorScope()), DepClassTy::NONE,
            IsKnownNonNull);
        if (IsKnownNonNull)
          KnownUBInsts.insert(&I);
      }

      return true;
    };

    bool UsedAssumedInformation = false;
    A.checkForAllInstructions(InspectMemAccessInstForUB, *this,
                              {Instruction::Load, Instruction::Store,
                               Instruction::AtomicCmpXchg,
                               Instruction::AtomicRMW},
                              UsedAssumedInformation,
                              /* CheckBBLivenessOnly */ true);
    A.checkForAllInstructions(InspectBrInstForUB, *this, {Instruction::Br},
                              UsedAssumedInformation,
                              /* CheckBBLivenessOnly */ true);
    A.checkForAllCallLikeInstructions(InspectCallSiteForUB, *this,
                                      UsedAssumedInformation);

    // If the returned position of the anchor scope has noundef attriubte, check
    // all returned instructions.
    if (!getAnchorScope()->getReturnType()->isVoidTy()) {
      const IRPosition &ReturnIRP = IRPosition::returned(*getAnchorScope());
      if (!A.isAssumedDead(ReturnIRP, this, nullptr, UsedAssumedInformation)) {
        bool IsKnownNoUndef;
        AA::hasAssumedIRAttr<Attribute::NoUndef>(
            A, this, ReturnIRP, DepClassTy::NONE, IsKnownNoUndef);
        if (IsKnownNoUndef)
          A.checkForAllInstructions(InspectReturnInstForUB, *this,
                                    {Instruction::Ret}, UsedAssumedInformation,
                                    /* CheckBBLivenessOnly */ true);
      }
    }

    if (NoUBPrevSize != AssumedNoUBInsts.size() ||
        UBPrevSize != KnownUBInsts.size())
      return ChangeStatus::CHANGED;
    return ChangeStatus::UNCHANGED;
  }

  bool isKnownToCauseUB(Instruction *I) const override {
    return KnownUBInsts.count(I);
  }

  bool isAssumedToCauseUB(Instruction *I) const override {
    // In simple words, if an instruction is not in the assumed to _not_
    // cause UB, then it is assumed UB (that includes those
    // in the KnownUBInsts set). The rest is boilerplate
    // is to ensure that it is one of the instructions we test
    // for UB.

    switch (I->getOpcode()) {
    case Instruction::Load:
    case Instruction::Store:
    case Instruction::AtomicCmpXchg:
    case Instruction::AtomicRMW:
      return !AssumedNoUBInsts.count(I);
    case Instruction::Br: {
      auto *BrInst = cast<BranchInst>(I);
      if (BrInst->isUnconditional())
        return false;
      return !AssumedNoUBInsts.count(I);
    } break;
    default:
      return false;
    }
    return false;
  }

  ChangeStatus manifest(Attributor &A) override {
    if (KnownUBInsts.empty())
      return ChangeStatus::UNCHANGED;
    for (Instruction *I : KnownUBInsts)
      A.changeToUnreachableAfterManifest(I);
    return ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "undefined-behavior" : "no-ub";
  }

  /// Note: The correctness of this analysis depends on the fact that the
  /// following 2 sets will stop changing after some point.
  /// "Change" here means that their size changes.
  /// The size of each set is monotonically increasing
  /// (we only add items to them) and it is upper bounded by the number of
  /// instructions in the processed function (we can never save more
  /// elements in either set than this number). Hence, at some point,
  /// they will stop increasing.
  /// Consequently, at some point, both sets will have stopped
  /// changing, effectively making the analysis reach a fixpoint.

  /// Note: These 2 sets are disjoint and an instruction can be considered
  /// one of 3 things:
  /// 1) Known to cause UB (AAUndefinedBehavior could prove it) and put it in
  ///    the KnownUBInsts set.
  /// 2) Assumed to cause UB (in every updateImpl, AAUndefinedBehavior
  ///    has a reason to assume it).
  /// 3) Assumed to not cause UB. very other instruction - AAUndefinedBehavior
  ///    could not find a reason to assume or prove that it can cause UB,
  ///    hence it assumes it doesn't. We have a set for these instructions
  ///    so that we don't reprocess them in every update.
  ///    Note however that instructions in this set may cause UB.

protected:
  /// A set of all live instructions _known_ to cause UB.
  SmallPtrSet<Instruction *, 8> KnownUBInsts;

private:
  /// A set of all the (live) instructions that are assumed to _not_ cause UB.
  SmallPtrSet<Instruction *, 8> AssumedNoUBInsts;

  // Should be called on updates in which if we're processing an instruction
  // \p I that depends on a value \p V, one of the following has to happen:
  // - If the value is assumed, then stop.
  // - If the value is known but undef, then consider it UB.
  // - Otherwise, do specific processing with the simplified value.
  // We return std::nullopt in the first 2 cases to signify that an appropriate
  // action was taken and the caller should stop.
  // Otherwise, we return the simplified value that the caller should
  // use for specific processing.
  std::optional<Value *> stopOnUndefOrAssumed(Attributor &A, Value *V,
                                              Instruction *I) {
    bool UsedAssumedInformation = false;
    std::optional<Value *> SimplifiedV =
        A.getAssumedSimplified(IRPosition::value(*V), *this,
                               UsedAssumedInformation, AA::Interprocedural);
    if (!UsedAssumedInformation) {
      // Don't depend on assumed values.
      if (!SimplifiedV) {
        // If it is known (which we tested above) but it doesn't have a value,
        // then we can assume `undef` and hence the instruction is UB.
        KnownUBInsts.insert(I);
        return std::nullopt;
      }
      if (!*SimplifiedV)
        return nullptr;
      V = *SimplifiedV;
    }
    if (isa<UndefValue>(V)) {
      KnownUBInsts.insert(I);
      return std::nullopt;
    }
    return V;
  }
};

struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {
  AAUndefinedBehaviorFunction(const IRPosition &IRP, Attributor &A)
      : AAUndefinedBehaviorImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECL(UndefinedBehaviorInstruction, Instruction,
               "Number of instructions known to have UB");
    BUILD_STAT_NAME(UndefinedBehaviorInstruction, Instruction) +=
        KnownUBInsts.size();
  }
};
} // namespace

/// ------------------------ Will-Return Attributes ----------------------------

namespace {
// Helper function that checks whether a function has any cycle which we don't
// know if it is bounded or not.
// Loops with maximum trip count are considered bounded, any other cycle not.
static bool mayContainUnboundedCycle(Function &F, Attributor &A) {
  ScalarEvolution *SE =
      A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(F);
  LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(F);
  // If either SCEV or LoopInfo is not available for the function then we assume
  // any cycle to be unbounded cycle.
  // We use scc_iterator which uses Tarjan algorithm to find all the maximal
  // SCCs.To detect if there's a cycle, we only need to find the maximal ones.
  if (!SE || !LI) {
    for (scc_iterator<Function *> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI)
      if (SCCI.hasCycle())
        return true;
    return false;
  }

  // If there's irreducible control, the function may contain non-loop cycles.
  if (mayContainIrreducibleControl(F, LI))
    return true;

  // Any loop that does not have a max trip count is considered unbounded cycle.
  for (auto *L : LI->getLoopsInPreorder()) {
    if (!SE->getSmallConstantMaxTripCount(L))
      return true;
  }
  return false;
}

struct AAWillReturnImpl : public AAWillReturn {
  AAWillReturnImpl(const IRPosition &IRP, Attributor &A)
      : AAWillReturn(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::WillReturn>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// Check for `mustprogress` and `readonly` as they imply `willreturn`.
  bool isImpliedByMustprogressAndReadonly(Attributor &A, bool KnownOnly) {
    if (!A.hasAttr(getIRPosition(), {Attribute::MustProgress}))
      return false;

    bool IsKnown;
    if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
      return IsKnown || !KnownOnly;
    return false;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
      return ChangeStatus::UNCHANGED;

    auto CheckForWillReturn = [&](Instruction &I) {
      IRPosition IPos = IRPosition::callsite_function(cast<CallBase>(I));
      bool IsKnown;
      if (AA::hasAssumedIRAttr<Attribute::WillReturn>(
              A, this, IPos, DepClassTy::REQUIRED, IsKnown)) {
        if (IsKnown)
          return true;
      } else {
        return false;
      }
      bool IsKnownNoRecurse;
      return AA::hasAssumedIRAttr<Attribute::NoRecurse>(
          A, this, IPos, DepClassTy::REQUIRED, IsKnownNoRecurse);
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallLikeInstructions(CheckForWillReturn, *this,
                                           UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "willreturn" : "may-noreturn";
  }
};

struct AAWillReturnFunction final : AAWillReturnImpl {
  AAWillReturnFunction(const IRPosition &IRP, Attributor &A)
      : AAWillReturnImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAWillReturnImpl::initialize(A);

    Function *F = getAnchorScope();
    assert(F && "Did expect an anchor function");
    if (F->isDeclaration() || mayContainUnboundedCycle(*F, A))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(willreturn) }
};

/// WillReturn attribute deduction for a call sites.
struct AAWillReturnCallSite final : AAWillReturnImpl {
  AAWillReturnCallSite(const IRPosition &IRP, Attributor &A)
      : AAWillReturnImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    if (isImpliedByMustprogressAndReadonly(A, /* KnownOnly */ false))
      return ChangeStatus::UNCHANGED;

    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnown;
    if (AA::hasAssumedIRAttr<Attribute::WillReturn>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnown))
      return ChangeStatus::UNCHANGED;
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(willreturn); }
};
} // namespace

/// -------------------AAIntraFnReachability Attribute--------------------------

/// All information associated with a reachability query. This boilerplate code
/// is used by both AAIntraFnReachability and AAInterFnReachability, with
/// different \p ToTy values.
template <typename ToTy> struct ReachabilityQueryInfo {
  enum class Reachable {
    No,
    Yes,
  };

  /// Start here,
  const Instruction *From = nullptr;
  /// reach this place,
  const ToTy *To = nullptr;
  /// without going through any of these instructions,
  const AA::InstExclusionSetTy *ExclusionSet = nullptr;
  /// and remember if it worked:
  Reachable Result = Reachable::No;

  ReachabilityQueryInfo(const Instruction *From, const ToTy *To)
      : From(From), To(To) {}

  /// Constructor replacement to ensure unique and stable sets are used for the
  /// cache.
  ReachabilityQueryInfo(Attributor &A, const Instruction &From, const ToTy &To,
                        const AA::InstExclusionSetTy *ES, bool MakeUnique)
      : From(&From), To(&To), ExclusionSet(ES) {

    if (!ES || ES->empty()) {
      ExclusionSet = nullptr;
    } else if (MakeUnique) {
      ExclusionSet = A.getInfoCache().getOrCreateUniqueBlockExecutionSet(ES);
    }
  }

  ReachabilityQueryInfo(const ReachabilityQueryInfo &RQI)
      : From(RQI.From), To(RQI.To), ExclusionSet(RQI.ExclusionSet) {}
};

namespace llvm {
template <typename ToTy> struct DenseMapInfo<ReachabilityQueryInfo<ToTy> *> {
  using InstSetDMI = DenseMapInfo<const AA::InstExclusionSetTy *>;
  using PairDMI = DenseMapInfo<std::pair<const Instruction *, const ToTy *>>;

  static ReachabilityQueryInfo<ToTy> EmptyKey;
  static ReachabilityQueryInfo<ToTy> TombstoneKey;

  static inline ReachabilityQueryInfo<ToTy> *getEmptyKey() { return &EmptyKey; }
  static inline ReachabilityQueryInfo<ToTy> *getTombstoneKey() {
    return &TombstoneKey;
  }
  static unsigned getHashValue(const ReachabilityQueryInfo<ToTy> *RQI) {
    unsigned H = PairDMI ::getHashValue({RQI->From, RQI->To});
    H += InstSetDMI::getHashValue(RQI->ExclusionSet);
    return H;
  }
  static bool isEqual(const ReachabilityQueryInfo<ToTy> *LHS,
                      const ReachabilityQueryInfo<ToTy> *RHS) {
    if (!PairDMI::isEqual({LHS->From, LHS->To}, {RHS->From, RHS->To}))
      return false;
    return InstSetDMI::isEqual(LHS->ExclusionSet, RHS->ExclusionSet);
  }
};

#define DefineKeys(ToTy)                                                       \
  template <>                                                                  \
  ReachabilityQueryInfo<ToTy>                                                  \
      DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::EmptyKey =                  \
          ReachabilityQueryInfo<ToTy>(                                         \
              DenseMapInfo<const Instruction *>::getEmptyKey(),                \
              DenseMapInfo<const ToTy *>::getEmptyKey());                      \
  template <>                                                                  \
  ReachabilityQueryInfo<ToTy>                                                  \
      DenseMapInfo<ReachabilityQueryInfo<ToTy> *>::TombstoneKey =              \
          ReachabilityQueryInfo<ToTy>(                                         \
              DenseMapInfo<const Instruction *>::getTombstoneKey(),            \
              DenseMapInfo<const ToTy *>::getTombstoneKey());

DefineKeys(Instruction) DefineKeys(Function)
#undef DefineKeys

} // namespace llvm

namespace {

template <typename BaseTy, typename ToTy>
struct CachedReachabilityAA : public BaseTy {
  using RQITy = ReachabilityQueryInfo<ToTy>;

  CachedReachabilityAA(const IRPosition &IRP, Attributor &A) : BaseTy(IRP, A) {}

  /// See AbstractAttribute::isQueryAA.
  bool isQueryAA() const override { return true; }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    InUpdate = true;
    for (unsigned u = 0, e = QueryVector.size(); u < e; ++u) {
      RQITy *RQI = QueryVector[u];
      if (RQI->Result == RQITy::Reachable::No && isReachableImpl(A, *RQI))
        Changed = ChangeStatus::CHANGED;
    }
    InUpdate = false;
    return Changed;
  }

  virtual bool isReachableImpl(Attributor &A, RQITy &RQI) = 0;

  bool rememberResult(Attributor &A, typename RQITy::Reachable Result,
                      RQITy &RQI, bool UsedExclusionSet) {
    RQI.Result = Result;

    // Remove the temporary RQI from the cache.
    if (!InUpdate)
      QueryCache.erase(&RQI);

    // Insert a plain RQI (w/o exclusion set) if that makes sense. Two options:
    // 1) If it is reachable, it doesn't matter if we have an exclusion set for
    // this query. 2) We did not use the exclusion set, potentially because
    // there is none.
    if (Result == RQITy::Reachable::Yes || !UsedExclusionSet) {
      RQITy PlainRQI(RQI.From, RQI.To);
      if (!QueryCache.count(&PlainRQI)) {
        RQITy *RQIPtr = new (A.Allocator) RQITy(RQI.From, RQI.To);
        RQIPtr->Result = Result;
        QueryVector.push_back(RQIPtr);
        QueryCache.insert(RQIPtr);
      }
    }

    // Check if we need to insert a new permanent RQI with the exclusion set.
    if (!InUpdate && Result != RQITy::Reachable::Yes && UsedExclusionSet) {
      assert((!RQI.ExclusionSet || !RQI.ExclusionSet->empty()) &&
             "Did not expect empty set!");
      RQITy *RQIPtr = new (A.Allocator)
          RQITy(A, *RQI.From, *RQI.To, RQI.ExclusionSet, true);
      assert(RQIPtr->Result == RQITy::Reachable::No && "Already reachable?");
      RQIPtr->Result = Result;
      assert(!QueryCache.count(RQIPtr));
      QueryVector.push_back(RQIPtr);
      QueryCache.insert(RQIPtr);
    }

    if (Result == RQITy::Reachable::No && !InUpdate)
      A.registerForUpdate(*this);
    return Result == RQITy::Reachable::Yes;
  }

  const std::string getAsStr(Attributor *A) const override {
    // TODO: Return the number of reachable queries.
    return "#queries(" + std::to_string(QueryVector.size()) + ")";
  }

  bool checkQueryCache(Attributor &A, RQITy &StackRQI,
                       typename RQITy::Reachable &Result) {
    if (!this->getState().isValidState()) {
      Result = RQITy::Reachable::Yes;
      return true;
    }

    // If we have an exclusion set we might be able to find our answer by
    // ignoring it first.
    if (StackRQI.ExclusionSet) {
      RQITy PlainRQI(StackRQI.From, StackRQI.To);
      auto It = QueryCache.find(&PlainRQI);
      if (It != QueryCache.end() && (*It)->Result == RQITy::Reachable::No) {
        Result = RQITy::Reachable::No;
        return true;
      }
    }

    auto It = QueryCache.find(&StackRQI);
    if (It != QueryCache.end()) {
      Result = (*It)->Result;
      return true;
    }

    // Insert a temporary for recursive queries. We will replace it with a
    // permanent entry later.
    QueryCache.insert(&StackRQI);
    return false;
  }

private:
  bool InUpdate = false;
  SmallVector<RQITy *> QueryVector;
  DenseSet<RQITy *> QueryCache;
};

struct AAIntraFnReachabilityFunction final
    : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {
  using Base = CachedReachabilityAA<AAIntraFnReachability, Instruction>;
  AAIntraFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  bool isAssumedReachable(
      Attributor &A, const Instruction &From, const Instruction &To,
      const AA::InstExclusionSetTy *ExclusionSet) const override {
    auto *NonConstThis = const_cast<AAIntraFnReachabilityFunction *>(this);
    if (&From == &To)
      return true;

    RQITy StackRQI(A, From, To, ExclusionSet, false);
    typename RQITy::Reachable Result;
    if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
      return NonConstThis->isReachableImpl(A, StackRQI);
    return Result == RQITy::Reachable::Yes;
  }

  ChangeStatus updateImpl(Attributor &A) override {
    // We only depend on liveness. DeadEdges is all we care about, check if any
    // of them changed.
    auto *LivenessAA =
        A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
    if (LivenessAA && llvm::all_of(DeadEdges, [&](const auto &DeadEdge) {
          return LivenessAA->isEdgeDead(DeadEdge.first, DeadEdge.second);
        })) {
      return ChangeStatus::UNCHANGED;
    }
    DeadEdges.clear();
    return Base::updateImpl(A);
  }

  bool isReachableImpl(Attributor &A, RQITy &RQI) override {
    const Instruction *Origin = RQI.From;
    bool UsedExclusionSet = false;

    auto WillReachInBlock = [&](const Instruction &From, const Instruction &To,
                                const AA::InstExclusionSetTy *ExclusionSet) {
      const Instruction *IP = &From;
      while (IP && IP != &To) {
        if (ExclusionSet && IP != Origin && ExclusionSet->count(IP)) {
          UsedExclusionSet = true;
          break;
        }
        IP = IP->getNextNode();
      }
      return IP == &To;
    };

    const BasicBlock *FromBB = RQI.From->getParent();
    const BasicBlock *ToBB = RQI.To->getParent();
    assert(FromBB->getParent() == ToBB->getParent() &&
           "Not an intra-procedural query!");

    // Check intra-block reachability, however, other reaching paths are still
    // possible.
    if (FromBB == ToBB &&
        WillReachInBlock(*RQI.From, *RQI.To, RQI.ExclusionSet))
      return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet);

    // Check if reaching the ToBB block is sufficient or if even that would not
    // ensure reaching the target. In the latter case we are done.
    if (!WillReachInBlock(ToBB->front(), *RQI.To, RQI.ExclusionSet))
      return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);

    SmallPtrSet<const BasicBlock *, 16> ExclusionBlocks;
    if (RQI.ExclusionSet)
      for (auto *I : *RQI.ExclusionSet)
        ExclusionBlocks.insert(I->getParent());

    // Check if we make it out of the FromBB block at all.
    if (ExclusionBlocks.count(FromBB) &&
        !WillReachInBlock(*RQI.From, *FromBB->getTerminator(),
                          RQI.ExclusionSet))
      return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);

    SmallPtrSet<const BasicBlock *, 16> Visited;
    SmallVector<const BasicBlock *, 16> Worklist;
    Worklist.push_back(FromBB);

    DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> LocalDeadEdges;
    auto *LivenessAA =
        A.getAAFor<AAIsDead>(*this, getIRPosition(), DepClassTy::OPTIONAL);
    while (!Worklist.empty()) {
      const BasicBlock *BB = Worklist.pop_back_val();
      if (!Visited.insert(BB).second)
        continue;
      for (const BasicBlock *SuccBB : successors(BB)) {
        if (LivenessAA && LivenessAA->isEdgeDead(BB, SuccBB)) {
          LocalDeadEdges.insert({BB, SuccBB});
          continue;
        }
        // We checked before if we just need to reach the ToBB block.
        if (SuccBB == ToBB)
          return rememberResult(A, RQITy::Reachable::Yes, RQI,
                                UsedExclusionSet);
        if (ExclusionBlocks.count(SuccBB)) {
          UsedExclusionSet = true;
          continue;
        }
        Worklist.push_back(SuccBB);
      }
    }

    DeadEdges.insert(LocalDeadEdges.begin(), LocalDeadEdges.end());
    return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}

private:
  // Set of assumed dead edges we used in the last query. If any changes we
  // update the state.
  DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> DeadEdges;
};
} // namespace

/// ------------------------ NoAlias Argument Attribute ------------------------

bool AANoAlias::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {
  assert(ImpliedAttributeKind == Attribute::NoAlias &&
         "Unexpected attribute kind");
  Value *Val = &IRP.getAssociatedValue();
  if (IRP.getPositionKind() != IRP_CALL_SITE_ARGUMENT) {
    if (isa<AllocaInst>(Val))
      return true;
  } else {
    IgnoreSubsumingPositions = true;
  }

  if (isa<UndefValue>(Val))
    return true;

  if (isa<ConstantPointerNull>(Val) &&
      !NullPointerIsDefined(IRP.getAnchorScope(),
                            Val->getType()->getPointerAddressSpace()))
    return true;

  if (A.hasAttr(IRP, {Attribute::ByVal, Attribute::NoAlias},
                IgnoreSubsumingPositions, Attribute::NoAlias))
    return true;

  return false;
}

namespace {
struct AANoAliasImpl : AANoAlias {
  AANoAliasImpl(const IRPosition &IRP, Attributor &A) : AANoAlias(IRP, A) {
    assert(getAssociatedType()->isPointerTy() &&
           "Noalias is a pointer attribute");
  }

  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "noalias" : "may-alias";
  }
};

/// NoAlias attribute for a floating value.
struct AANoAliasFloating final : AANoAliasImpl {
  AANoAliasFloating(const IRPosition &IRP, Attributor &A)
      : AANoAliasImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Implement this.
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(noalias)
  }
};

/// NoAlias attribute for an argument.
struct AANoAliasArgument final
    : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl,
                                      AANoAlias::StateType, false,
                                      Attribute::NoAlias> {
  using Base = AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl,
                                               AANoAlias::StateType, false,
                                               Attribute::NoAlias>;
  AANoAliasArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}

  /// See AbstractAttribute::update(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // We have to make sure no-alias on the argument does not break
    // synchronization when this is a callback argument, see also [1] below.
    // If synchronization cannot be affected, we delegate to the base updateImpl
    // function, otherwise we give up for now.

    // If the function is no-sync, no-alias cannot break synchronization.
    bool IsKnownNoSycn;
    if (AA::hasAssumedIRAttr<Attribute::NoSync>(
            A, this, IRPosition::function_scope(getIRPosition()),
            DepClassTy::OPTIONAL, IsKnownNoSycn))
      return Base::updateImpl(A);

    // If the argument is read-only, no-alias cannot break synchronization.
    bool IsKnown;
    if (AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
      return Base::updateImpl(A);

    // If the argument is never passed through callbacks, no-alias cannot break
    // synchronization.
    bool UsedAssumedInformation = false;
    if (A.checkForAllCallSites(
            [](AbstractCallSite ACS) { return !ACS.isCallbackCall(); }, *this,
            true, UsedAssumedInformation))
      return Base::updateImpl(A);

    // TODO: add no-alias but make sure it doesn't break synchronization by
    // introducing fake uses. See:
    // [1] Compiler Optimizations for OpenMP, J. Doerfert and H. Finkel,
    //     International Workshop on OpenMP 2018,
    //     http://compilers.cs.uni-saarland.de/people/doerfert/par_opt18.pdf

    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noalias) }
};

struct AANoAliasCallSiteArgument final : AANoAliasImpl {
  AANoAliasCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANoAliasImpl(IRP, A) {}

  /// Determine if the underlying value may alias with the call site argument
  /// \p OtherArgNo of \p ICS (= the underlying call site).
  bool mayAliasWithArgument(Attributor &A, AAResults *&AAR,
                            const AAMemoryBehavior &MemBehaviorAA,
                            const CallBase &CB, unsigned OtherArgNo) {
    // We do not need to worry about aliasing with the underlying IRP.
    if (this->getCalleeArgNo() == (int)OtherArgNo)
      return false;

    // If it is not a pointer or pointer vector we do not alias.
    const Value *ArgOp = CB.getArgOperand(OtherArgNo);
    if (!ArgOp->getType()->isPtrOrPtrVectorTy())
      return false;

    auto *CBArgMemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
        *this, IRPosition::callsite_argument(CB, OtherArgNo), DepClassTy::NONE);

    // If the argument is readnone, there is no read-write aliasing.
    if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadNone()) {
      A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
      return false;
    }

    // If the argument is readonly and the underlying value is readonly, there
    // is no read-write aliasing.
    bool IsReadOnly = MemBehaviorAA.isAssumedReadOnly();
    if (CBArgMemBehaviorAA && CBArgMemBehaviorAA->isAssumedReadOnly() &&
        IsReadOnly) {
      A.recordDependence(MemBehaviorAA, *this, DepClassTy::OPTIONAL);
      A.recordDependence(*CBArgMemBehaviorAA, *this, DepClassTy::OPTIONAL);
      return false;
    }

    // We have to utilize actual alias analysis queries so we need the object.
    if (!AAR)
      AAR = A.getInfoCache().getAnalysisResultForFunction<AAManager>(
          *getAnchorScope());

    // Try to rule it out at the call site.
    bool IsAliasing = !AAR || !AAR->isNoAlias(&getAssociatedValue(), ArgOp);
    LLVM_DEBUG(dbgs() << "[NoAliasCSArg] Check alias between "
                         "callsite arguments: "
                      << getAssociatedValue() << " " << *ArgOp << " => "
                      << (IsAliasing ? "" : "no-") << "alias \n");

    return IsAliasing;
  }

  bool isKnownNoAliasDueToNoAliasPreservation(
      Attributor &A, AAResults *&AAR, const AAMemoryBehavior &MemBehaviorAA) {
    // We can deduce "noalias" if the following conditions hold.
    // (i)   Associated value is assumed to be noalias in the definition.
    // (ii)  Associated value is assumed to be no-capture in all the uses
    //       possibly executed before this callsite.
    // (iii) There is no other pointer argument which could alias with the
    //       value.

    auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
      const auto *DerefAA = A.getAAFor<AADereferenceable>(
          *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
      return DerefAA ? DerefAA->getAssumedDereferenceableBytes() : 0;
    };

    const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
    const Function *ScopeFn = VIRP.getAnchorScope();
    // Check whether the value is captured in the scope using AANoCapture.
    // Look at CFG and check only uses possibly executed before this
    // callsite.
    auto UsePred = [&](const Use &U, bool &Follow) -> bool {
      Instruction *UserI = cast<Instruction>(U.getUser());

      // If UserI is the curr instruction and there is a single potential use of
      // the value in UserI we allow the use.
      // TODO: We should inspect the operands and allow those that cannot alias
      //       with the value.
      if (UserI == getCtxI() && UserI->getNumOperands() == 1)
        return true;

      if (ScopeFn) {
        if (auto *CB = dyn_cast<CallBase>(UserI)) {
          if (CB->isArgOperand(&U)) {

            unsigned ArgNo = CB->getArgOperandNo(&U);

            bool IsKnownNoCapture;
            if (AA::hasAssumedIRAttr<Attribute::NoCapture>(
                    A, this, IRPosition::callsite_argument(*CB, ArgNo),
                    DepClassTy::OPTIONAL, IsKnownNoCapture))
              return true;
          }
        }

        if (!AA::isPotentiallyReachable(
                A, *UserI, *getCtxI(), *this, /* ExclusionSet */ nullptr,
                [ScopeFn](const Function &Fn) { return &Fn != ScopeFn; }))
          return true;
      }

      // TODO: We should track the capturing uses in AANoCapture but the problem
      //       is CGSCC runs. For those we would need to "allow" AANoCapture for
      //       a value in the module slice.
      switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
      case UseCaptureKind::NO_CAPTURE:
        return true;
      case UseCaptureKind::MAY_CAPTURE:
        LLVM_DEBUG(dbgs() << "[AANoAliasCSArg] Unknown user: " << *UserI
                          << "\n");
        return false;
      case UseCaptureKind::PASSTHROUGH:
        Follow = true;
        return true;
      }
      llvm_unreachable("unknown UseCaptureKind");
    };

    bool IsKnownNoCapture;
    const AANoCapture *NoCaptureAA = nullptr;
    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
        A, this, VIRP, DepClassTy::NONE, IsKnownNoCapture, false, &NoCaptureAA);
    if (!IsAssumedNoCapture &&
        (!NoCaptureAA || !NoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
      if (!A.checkForAllUses(UsePred, *this, getAssociatedValue())) {
        LLVM_DEBUG(
            dbgs() << "[AANoAliasCSArg] " << getAssociatedValue()
                   << " cannot be noalias as it is potentially captured\n");
        return false;
      }
    }
    if (NoCaptureAA)
      A.recordDependence(*NoCaptureAA, *this, DepClassTy::OPTIONAL);

    // Check there is no other pointer argument which could alias with the
    // value passed at this call site.
    // TODO: AbstractCallSite
    const auto &CB = cast<CallBase>(getAnchorValue());
    for (unsigned OtherArgNo = 0; OtherArgNo < CB.arg_size(); OtherArgNo++)
      if (mayAliasWithArgument(A, AAR, MemBehaviorAA, CB, OtherArgNo))
        return false;

    return true;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // If the argument is readnone we are done as there are no accesses via the
    // argument.
    auto *MemBehaviorAA =
        A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
    if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
      A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
      return ChangeStatus::UNCHANGED;
    }

    bool IsKnownNoAlias;
    const IRPosition &VIRP = IRPosition::value(getAssociatedValue());
    if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
            A, this, VIRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
      LLVM_DEBUG(dbgs() << "[AANoAlias] " << getAssociatedValue()
                        << " is not no-alias at the definition\n");
      return indicatePessimisticFixpoint();
    }

    AAResults *AAR = nullptr;
    if (MemBehaviorAA &&
        isKnownNoAliasDueToNoAliasPreservation(A, AAR, *MemBehaviorAA)) {
      LLVM_DEBUG(
          dbgs() << "[AANoAlias] No-Alias deduced via no-alias preservation\n");
      return ChangeStatus::UNCHANGED;
    }

    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noalias) }
};

/// NoAlias attribute for function return value.
struct AANoAliasReturned final : AANoAliasImpl {
  AANoAliasReturned(const IRPosition &IRP, Attributor &A)
      : AANoAliasImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {

    auto CheckReturnValue = [&](Value &RV) -> bool {
      if (Constant *C = dyn_cast<Constant>(&RV))
        if (C->isNullValue() || isa<UndefValue>(C))
          return true;

      /// For now, we can only deduce noalias if we have call sites.
      /// FIXME: add more support.
      if (!isa<CallBase>(&RV))
        return false;

      const IRPosition &RVPos = IRPosition::value(RV);
      bool IsKnownNoAlias;
      if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
              A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoAlias))
        return false;

      bool IsKnownNoCapture;
      const AANoCapture *NoCaptureAA = nullptr;
      bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
          A, this, RVPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
          &NoCaptureAA);
      return IsAssumedNoCapture ||
             (NoCaptureAA && NoCaptureAA->isAssumedNoCaptureMaybeReturned());
    };

    if (!A.checkForAllReturnedValues(CheckReturnValue, *this))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noalias) }
};

/// NoAlias attribute deduction for a call site return value.
struct AANoAliasCallSiteReturned final : AANoAliasImpl {
  AANoAliasCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AANoAliasImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::returned(*F);
    bool IsKnownNoAlias;
    if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownNoAlias))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noalias); }
};
} // namespace

/// -------------------AAIsDead Function Attribute-----------------------

namespace {
struct AAIsDeadValueImpl : public AAIsDead {
  AAIsDeadValueImpl(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}

  /// See AAIsDead::isAssumedDead().
  bool isAssumedDead() const override { return isAssumed(IS_DEAD); }

  /// See AAIsDead::isKnownDead().
  bool isKnownDead() const override { return isKnown(IS_DEAD); }

  /// See AAIsDead::isAssumedDead(BasicBlock *).
  bool isAssumedDead(const BasicBlock *BB) const override { return false; }

  /// See AAIsDead::isKnownDead(BasicBlock *).
  bool isKnownDead(const BasicBlock *BB) const override { return false; }

  /// See AAIsDead::isAssumedDead(Instruction *I).
  bool isAssumedDead(const Instruction *I) const override {
    return I == getCtxI() && isAssumedDead();
  }

  /// See AAIsDead::isKnownDead(Instruction *I).
  bool isKnownDead(const Instruction *I) const override {
    return isAssumedDead(I) && isKnownDead();
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return isAssumedDead() ? "assumed-dead" : "assumed-live";
  }

  /// Check if all uses are assumed dead.
  bool areAllUsesAssumedDead(Attributor &A, Value &V) {
    // Callers might not check the type, void has no uses.
    if (V.getType()->isVoidTy() || V.use_empty())
      return true;

    // If we replace a value with a constant there are no uses left afterwards.
    if (!isa<Constant>(V)) {
      if (auto *I = dyn_cast<Instruction>(&V))
        if (!A.isRunOn(*I->getFunction()))
          return false;
      bool UsedAssumedInformation = false;
      std::optional<Constant *> C =
          A.getAssumedConstant(V, *this, UsedAssumedInformation);
      if (!C || *C)
        return true;
    }

    auto UsePred = [&](const Use &U, bool &Follow) { return false; };
    // Explicitly set the dependence class to required because we want a long
    // chain of N dependent instructions to be considered live as soon as one is
    // without going through N update cycles. This is not required for
    // correctness.
    return A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ false,
                             DepClassTy::REQUIRED,
                             /* IgnoreDroppableUses */ false);
  }

  /// Determine if \p I is assumed to be side-effect free.
  bool isAssumedSideEffectFree(Attributor &A, Instruction *I) {
    if (!I || wouldInstructionBeTriviallyDead(I))
      return true;

    auto *CB = dyn_cast<CallBase>(I);
    if (!CB || isa<IntrinsicInst>(CB))
      return false;

    const IRPosition &CallIRP = IRPosition::callsite_function(*CB);

    bool IsKnownNoUnwind;
    if (!AA::hasAssumedIRAttr<Attribute::NoUnwind>(
            A, this, CallIRP, DepClassTy::OPTIONAL, IsKnownNoUnwind))
      return false;

    bool IsKnown;
    return AA::isAssumedReadOnly(A, CallIRP, *this, IsKnown);
  }
};

struct AAIsDeadFloating : public AAIsDeadValueImpl {
  AAIsDeadFloating(const IRPosition &IRP, Attributor &A)
      : AAIsDeadValueImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAIsDeadValueImpl::initialize(A);

    if (isa<UndefValue>(getAssociatedValue())) {
      indicatePessimisticFixpoint();
      return;
    }

    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
    if (!isAssumedSideEffectFree(A, I)) {
      if (!isa_and_nonnull<StoreInst>(I) && !isa_and_nonnull<FenceInst>(I))
        indicatePessimisticFixpoint();
      else
        removeAssumedBits(HAS_NO_EFFECT);
    }
  }

  bool isDeadFence(Attributor &A, FenceInst &FI) {
    const auto *ExecDomainAA = A.lookupAAFor<AAExecutionDomain>(
        IRPosition::function(*FI.getFunction()), *this, DepClassTy::NONE);
    if (!ExecDomainAA || !ExecDomainAA->isNoOpFence(FI))
      return false;
    A.recordDependence(*ExecDomainAA, *this, DepClassTy::OPTIONAL);
    return true;
  }

  bool isDeadStore(Attributor &A, StoreInst &SI,
                   SmallSetVector<Instruction *, 8> *AssumeOnlyInst = nullptr) {
    // Lang ref now states volatile store is not UB/dead, let's skip them.
    if (SI.isVolatile())
      return false;

    // If we are collecting assumes to be deleted we are in the manifest stage.
    // It's problematic to collect the potential copies again now so we use the
    // cached ones.
    bool UsedAssumedInformation = false;
    if (!AssumeOnlyInst) {
      PotentialCopies.clear();
      if (!AA::getPotentialCopiesOfStoredValue(A, SI, PotentialCopies, *this,
                                               UsedAssumedInformation)) {
        LLVM_DEBUG(
            dbgs()
            << "[AAIsDead] Could not determine potential copies of store!\n");
        return false;
      }
    }
    LLVM_DEBUG(dbgs() << "[AAIsDead] Store has " << PotentialCopies.size()
                      << " potential copies.\n");

    InformationCache &InfoCache = A.getInfoCache();
    return llvm::all_of(PotentialCopies, [&](Value *V) {
      if (A.isAssumedDead(IRPosition::value(*V), this, nullptr,
                          UsedAssumedInformation))
        return true;
      if (auto *LI = dyn_cast<LoadInst>(V)) {
        if (llvm::all_of(LI->uses(), [&](const Use &U) {
              auto &UserI = cast<Instruction>(*U.getUser());
              if (InfoCache.isOnlyUsedByAssume(UserI)) {
                if (AssumeOnlyInst)
                  AssumeOnlyInst->insert(&UserI);
                return true;
              }
              return A.isAssumedDead(U, this, nullptr, UsedAssumedInformation);
            })) {
          return true;
        }
      }
      LLVM_DEBUG(dbgs() << "[AAIsDead] Potential copy " << *V
                        << " is assumed live!\n");
      return false;
    });
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
    if (isa_and_nonnull<StoreInst>(I))
      if (isValidState())
        return "assumed-dead-store";
    if (isa_and_nonnull<FenceInst>(I))
      if (isValidState())
        return "assumed-dead-fence";
    return AAIsDeadValueImpl::getAsStr(A);
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
    if (auto *SI = dyn_cast_or_null<StoreInst>(I)) {
      if (!isDeadStore(A, *SI))
        return indicatePessimisticFixpoint();
    } else if (auto *FI = dyn_cast_or_null<FenceInst>(I)) {
      if (!isDeadFence(A, *FI))
        return indicatePessimisticFixpoint();
    } else {
      if (!isAssumedSideEffectFree(A, I))
        return indicatePessimisticFixpoint();
      if (!areAllUsesAssumedDead(A, getAssociatedValue()))
        return indicatePessimisticFixpoint();
    }
    return ChangeStatus::UNCHANGED;
  }

  bool isRemovableStore() const override {
    return isAssumed(IS_REMOVABLE) && isa<StoreInst>(&getAssociatedValue());
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    Value &V = getAssociatedValue();
    if (auto *I = dyn_cast<Instruction>(&V)) {
      // If we get here we basically know the users are all dead. We check if
      // isAssumedSideEffectFree returns true here again because it might not be
      // the case and only the users are dead but the instruction (=call) is
      // still needed.
      if (auto *SI = dyn_cast<StoreInst>(I)) {
        SmallSetVector<Instruction *, 8> AssumeOnlyInst;
        bool IsDead = isDeadStore(A, *SI, &AssumeOnlyInst);
        (void)IsDead;
        assert(IsDead && "Store was assumed to be dead!");
        A.deleteAfterManifest(*I);
        for (size_t i = 0; i < AssumeOnlyInst.size(); ++i) {
          Instruction *AOI = AssumeOnlyInst[i];
          for (auto *Usr : AOI->users())
            AssumeOnlyInst.insert(cast<Instruction>(Usr));
          A.deleteAfterManifest(*AOI);
        }
        return ChangeStatus::CHANGED;
      }
      if (auto *FI = dyn_cast<FenceInst>(I)) {
        assert(isDeadFence(A, *FI));
        A.deleteAfterManifest(*FI);
        return ChangeStatus::CHANGED;
      }
      if (isAssumedSideEffectFree(A, I) && !isa<InvokeInst>(I)) {
        A.deleteAfterManifest(*I);
        return ChangeStatus::CHANGED;
      }
    }
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(IsDead)
  }

private:
  // The potential copies of a dead store, used for deletion during manifest.
  SmallSetVector<Value *, 4> PotentialCopies;
};

struct AAIsDeadArgument : public AAIsDeadFloating {
  AAIsDeadArgument(const IRPosition &IRP, Attributor &A)
      : AAIsDeadFloating(IRP, A) {}

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    Argument &Arg = *getAssociatedArgument();
    if (A.isValidFunctionSignatureRewrite(Arg, /* ReplacementTypes */ {}))
      if (A.registerFunctionSignatureRewrite(
              Arg, /* ReplacementTypes */ {},
              Attributor::ArgumentReplacementInfo::CalleeRepairCBTy{},
              Attributor::ArgumentReplacementInfo::ACSRepairCBTy{})) {
        return ChangeStatus::CHANGED;
      }
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(IsDead) }
};

struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {
  AAIsDeadCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAIsDeadValueImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAIsDeadValueImpl::initialize(A);
    if (isa<UndefValue>(getAssociatedValue()))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    if (!Arg)
      return indicatePessimisticFixpoint();
    const IRPosition &ArgPos = IRPosition::argument(*Arg);
    auto *ArgAA = A.getAAFor<AAIsDead>(*this, ArgPos, DepClassTy::REQUIRED);
    if (!ArgAA)
      return indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(getState(), ArgAA->getState());
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    CallBase &CB = cast<CallBase>(getAnchorValue());
    Use &U = CB.getArgOperandUse(getCallSiteArgNo());
    assert(!isa<UndefValue>(U.get()) &&
           "Expected undef values to be filtered out!");
    UndefValue &UV = *UndefValue::get(U->getType());
    if (A.changeUseAfterManifest(U, UV))
      return ChangeStatus::CHANGED;
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(IsDead) }
};

struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {
  AAIsDeadCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAIsDeadFloating(IRP, A) {}

  /// See AAIsDead::isAssumedDead().
  bool isAssumedDead() const override {
    return AAIsDeadFloating::isAssumedDead() && IsAssumedSideEffectFree;
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAIsDeadFloating::initialize(A);
    if (isa<UndefValue>(getAssociatedValue())) {
      indicatePessimisticFixpoint();
      return;
    }

    // We track this separately as a secondary state.
    IsAssumedSideEffectFree = isAssumedSideEffectFree(A, getCtxI());
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    if (IsAssumedSideEffectFree && !isAssumedSideEffectFree(A, getCtxI())) {
      IsAssumedSideEffectFree = false;
      Changed = ChangeStatus::CHANGED;
    }
    if (!areAllUsesAssumedDead(A, getAssociatedValue()))
      return indicatePessimisticFixpoint();
    return Changed;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (IsAssumedSideEffectFree)
      STATS_DECLTRACK_CSRET_ATTR(IsDead)
    else
      STATS_DECLTRACK_CSRET_ATTR(UnusedResult)
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return isAssumedDead()
               ? "assumed-dead"
               : (getAssumed() ? "assumed-dead-users" : "assumed-live");
  }

private:
  bool IsAssumedSideEffectFree = true;
};

struct AAIsDeadReturned : public AAIsDeadValueImpl {
  AAIsDeadReturned(const IRPosition &IRP, Attributor &A)
      : AAIsDeadValueImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {

    bool UsedAssumedInformation = false;
    A.checkForAllInstructions([](Instruction &) { return true; }, *this,
                              {Instruction::Ret}, UsedAssumedInformation);

    auto PredForCallSite = [&](AbstractCallSite ACS) {
      if (ACS.isCallbackCall() || !ACS.getInstruction())
        return false;
      return areAllUsesAssumedDead(A, *ACS.getInstruction());
    };

    if (!A.checkForAllCallSites(PredForCallSite, *this, true,
                                UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // TODO: Rewrite the signature to return void?
    bool AnyChange = false;
    UndefValue &UV = *UndefValue::get(getAssociatedFunction()->getReturnType());
    auto RetInstPred = [&](Instruction &I) {
      ReturnInst &RI = cast<ReturnInst>(I);
      if (!isa<UndefValue>(RI.getReturnValue()))
        AnyChange |= A.changeUseAfterManifest(RI.getOperandUse(0), UV);
      return true;
    };
    bool UsedAssumedInformation = false;
    A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
                              UsedAssumedInformation);
    return AnyChange ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(IsDead) }
};

struct AAIsDeadFunction : public AAIsDead {
  AAIsDeadFunction(const IRPosition &IRP, Attributor &A) : AAIsDead(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    Function *F = getAnchorScope();
    assert(F && "Did expect an anchor function");
    if (!isAssumedDeadInternalFunction(A)) {
      ToBeExploredFrom.insert(&F->getEntryBlock().front());
      assumeLive(A, F->getEntryBlock());
    }
  }

  bool isAssumedDeadInternalFunction(Attributor &A) {
    if (!getAnchorScope()->hasLocalLinkage())
      return false;
    bool UsedAssumedInformation = false;
    return A.checkForAllCallSites([](AbstractCallSite) { return false; }, *this,
                                  true, UsedAssumedInformation);
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return "Live[#BB " + std::to_string(AssumedLiveBlocks.size()) + "/" +
           std::to_string(getAnchorScope()->size()) + "][#TBEP " +
           std::to_string(ToBeExploredFrom.size()) + "][#KDE " +
           std::to_string(KnownDeadEnds.size()) + "]";
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    assert(getState().isValidState() &&
           "Attempted to manifest an invalid state!");

    ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
    Function &F = *getAnchorScope();

    if (AssumedLiveBlocks.empty()) {
      A.deleteAfterManifest(F);
      return ChangeStatus::CHANGED;
    }

    // Flag to determine if we can change an invoke to a call assuming the
    // callee is nounwind. This is not possible if the personality of the
    // function allows to catch asynchronous exceptions.
    bool Invoke2CallAllowed = !mayCatchAsynchronousExceptions(F);

    KnownDeadEnds.set_union(ToBeExploredFrom);
    for (const Instruction *DeadEndI : KnownDeadEnds) {
      auto *CB = dyn_cast<CallBase>(DeadEndI);
      if (!CB)
        continue;
      bool IsKnownNoReturn;
      bool MayReturn = !AA::hasAssumedIRAttr<Attribute::NoReturn>(
          A, this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL,
          IsKnownNoReturn);
      if (MayReturn && (!Invoke2CallAllowed || !isa<InvokeInst>(CB)))
        continue;

      if (auto *II = dyn_cast<InvokeInst>(DeadEndI))
        A.registerInvokeWithDeadSuccessor(const_cast<InvokeInst &>(*II));
      else
        A.changeToUnreachableAfterManifest(
            const_cast<Instruction *>(DeadEndI->getNextNode()));
      HasChanged = ChangeStatus::CHANGED;
    }

    STATS_DECL(AAIsDead, BasicBlock, "Number of dead basic blocks deleted.");
    for (BasicBlock &BB : F)
      if (!AssumedLiveBlocks.count(&BB)) {
        A.deleteAfterManifest(BB);
        ++BUILD_STAT_NAME(AAIsDead, BasicBlock);
        HasChanged = ChangeStatus::CHANGED;
      }

    return HasChanged;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override;

  bool isEdgeDead(const BasicBlock *From, const BasicBlock *To) const override {
    assert(From->getParent() == getAnchorScope() &&
           To->getParent() == getAnchorScope() &&
           "Used AAIsDead of the wrong function");
    return isValidState() && !AssumedLiveEdges.count(std::make_pair(From, To));
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}

  /// Returns true if the function is assumed dead.
  bool isAssumedDead() const override { return false; }

  /// See AAIsDead::isKnownDead().
  bool isKnownDead() const override { return false; }

  /// See AAIsDead::isAssumedDead(BasicBlock *).
  bool isAssumedDead(const BasicBlock *BB) const override {
    assert(BB->getParent() == getAnchorScope() &&
           "BB must be in the same anchor scope function.");

    if (!getAssumed())
      return false;
    return !AssumedLiveBlocks.count(BB);
  }

  /// See AAIsDead::isKnownDead(BasicBlock *).
  bool isKnownDead(const BasicBlock *BB) const override {
    return getKnown() && isAssumedDead(BB);
  }

  /// See AAIsDead::isAssumed(Instruction *I).
  bool isAssumedDead(const Instruction *I) const override {
    assert(I->getParent()->getParent() == getAnchorScope() &&
           "Instruction must be in the same anchor scope function.");

    if (!getAssumed())
      return false;

    // If it is not in AssumedLiveBlocks then it for sure dead.
    // Otherwise, it can still be after noreturn call in a live block.
    if (!AssumedLiveBlocks.count(I->getParent()))
      return true;

    // If it is not after a liveness barrier it is live.
    const Instruction *PrevI = I->getPrevNode();
    while (PrevI) {
      if (KnownDeadEnds.count(PrevI) || ToBeExploredFrom.count(PrevI))
        return true;
      PrevI = PrevI->getPrevNode();
    }
    return false;
  }

  /// See AAIsDead::isKnownDead(Instruction *I).
  bool isKnownDead(const Instruction *I) const override {
    return getKnown() && isAssumedDead(I);
  }

  /// Assume \p BB is (partially) live now and indicate to the Attributor \p A
  /// that internal function called from \p BB should now be looked at.
  bool assumeLive(Attributor &A, const BasicBlock &BB) {
    if (!AssumedLiveBlocks.insert(&BB).second)
      return false;

    // We assume that all of BB is (probably) live now and if there are calls to
    // internal functions we will assume that those are now live as well. This
    // is a performance optimization for blocks with calls to a lot of internal
    // functions. It can however cause dead functions to be treated as live.
    for (const Instruction &I : BB)
      if (const auto *CB = dyn_cast<CallBase>(&I))
        if (auto *F = dyn_cast_if_present<Function>(CB->getCalledOperand()))
          if (F->hasLocalLinkage())
            A.markLiveInternalFunction(*F);
    return true;
  }

  /// Collection of instructions that need to be explored again, e.g., we
  /// did assume they do not transfer control to (one of their) successors.
  SmallSetVector<const Instruction *, 8> ToBeExploredFrom;

  /// Collection of instructions that are known to not transfer control.
  SmallSetVector<const Instruction *, 8> KnownDeadEnds;

  /// Collection of all assumed live edges
  DenseSet<std::pair<const BasicBlock *, const BasicBlock *>> AssumedLiveEdges;

  /// Collection of all assumed live BasicBlocks.
  DenseSet<const BasicBlock *> AssumedLiveBlocks;
};

static bool
identifyAliveSuccessors(Attributor &A, const CallBase &CB,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {
  const IRPosition &IPos = IRPosition::callsite_function(CB);

  bool IsKnownNoReturn;
  if (AA::hasAssumedIRAttr<Attribute::NoReturn>(
          A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoReturn))
    return !IsKnownNoReturn;
  if (CB.isTerminator())
    AliveSuccessors.push_back(&CB.getSuccessor(0)->front());
  else
    AliveSuccessors.push_back(CB.getNextNode());
  return false;
}

static bool
identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {
  bool UsedAssumedInformation =
      identifyAliveSuccessors(A, cast<CallBase>(II), AA, AliveSuccessors);

  // First, determine if we can change an invoke to a call assuming the
  // callee is nounwind. This is not possible if the personality of the
  // function allows to catch asynchronous exceptions.
  if (AAIsDeadFunction::mayCatchAsynchronousExceptions(*II.getFunction())) {
    AliveSuccessors.push_back(&II.getUnwindDest()->front());
  } else {
    const IRPosition &IPos = IRPosition::callsite_function(II);

    bool IsKnownNoUnwind;
    if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(
            A, &AA, IPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
      UsedAssumedInformation |= !IsKnownNoUnwind;
    } else {
      AliveSuccessors.push_back(&II.getUnwindDest()->front());
    }
  }
  return UsedAssumedInformation;
}

static bool
identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {
  bool UsedAssumedInformation = false;
  if (BI.getNumSuccessors() == 1) {
    AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
  } else {
    std::optional<Constant *> C =
        A.getAssumedConstant(*BI.getCondition(), AA, UsedAssumedInformation);
    if (!C || isa_and_nonnull<UndefValue>(*C)) {
      // No value yet, assume both edges are dead.
    } else if (isa_and_nonnull<ConstantInt>(*C)) {
      const BasicBlock *SuccBB =
          BI.getSuccessor(1 - cast<ConstantInt>(*C)->getValue().getZExtValue());
      AliveSuccessors.push_back(&SuccBB->front());
    } else {
      AliveSuccessors.push_back(&BI.getSuccessor(0)->front());
      AliveSuccessors.push_back(&BI.getSuccessor(1)->front());
      UsedAssumedInformation = false;
    }
  }
  return UsedAssumedInformation;
}

static bool
identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {
  bool UsedAssumedInformation = false;
  std::optional<Constant *> C =
      A.getAssumedConstant(*SI.getCondition(), AA, UsedAssumedInformation);
  if (!C || isa_and_nonnull<UndefValue>(*C)) {
    // No value yet, assume all edges are dead.
  } else if (isa_and_nonnull<ConstantInt>(*C)) {
    for (const auto &CaseIt : SI.cases()) {
      if (CaseIt.getCaseValue() == *C) {
        AliveSuccessors.push_back(&CaseIt.getCaseSuccessor()->front());
        return UsedAssumedInformation;
      }
    }
    AliveSuccessors.push_back(&SI.getDefaultDest()->front());
    return UsedAssumedInformation;
  } else {
    for (const BasicBlock *SuccBB : successors(SI.getParent()))
      AliveSuccessors.push_back(&SuccBB->front());
  }
  return UsedAssumedInformation;
}

ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {
  ChangeStatus Change = ChangeStatus::UNCHANGED;

  if (AssumedLiveBlocks.empty()) {
    if (isAssumedDeadInternalFunction(A))
      return ChangeStatus::UNCHANGED;

    Function *F = getAnchorScope();
    ToBeExploredFrom.insert(&F->getEntryBlock().front());
    assumeLive(A, F->getEntryBlock());
    Change = ChangeStatus::CHANGED;
  }

  LLVM_DEBUG(dbgs() << "[AAIsDead] Live [" << AssumedLiveBlocks.size() << "/"
                    << getAnchorScope()->size() << "] BBs and "
                    << ToBeExploredFrom.size() << " exploration points and "
                    << KnownDeadEnds.size() << " known dead ends\n");

  // Copy and clear the list of instructions we need to explore from. It is
  // refilled with instructions the next update has to look at.
  SmallVector<const Instruction *, 8> Worklist(ToBeExploredFrom.begin(),
                                               ToBeExploredFrom.end());
  decltype(ToBeExploredFrom) NewToBeExploredFrom;

  SmallVector<const Instruction *, 8> AliveSuccessors;
  while (!Worklist.empty()) {
    const Instruction *I = Worklist.pop_back_val();
    LLVM_DEBUG(dbgs() << "[AAIsDead] Exploration inst: " << *I << "\n");

    // Fast forward for uninteresting instructions. We could look for UB here
    // though.
    while (!I->isTerminator() && !isa<CallBase>(I))
      I = I->getNextNode();

    AliveSuccessors.clear();

    bool UsedAssumedInformation = false;
    switch (I->getOpcode()) {
    // TODO: look for (assumed) UB to backwards propagate "deadness".
    default:
      assert(I->isTerminator() &&
             "Expected non-terminators to be handled already!");
      for (const BasicBlock *SuccBB : successors(I->getParent()))
        AliveSuccessors.push_back(&SuccBB->front());
      break;
    case Instruction::Call:
      UsedAssumedInformation = identifyAliveSuccessors(A, cast<CallInst>(*I),
                                                       *this, AliveSuccessors);
      break;
    case Instruction::Invoke:
      UsedAssumedInformation = identifyAliveSuccessors(A, cast<InvokeInst>(*I),
                                                       *this, AliveSuccessors);
      break;
    case Instruction::Br:
      UsedAssumedInformation = identifyAliveSuccessors(A, cast<BranchInst>(*I),
                                                       *this, AliveSuccessors);
      break;
    case Instruction::Switch:
      UsedAssumedInformation = identifyAliveSuccessors(A, cast<SwitchInst>(*I),
                                                       *this, AliveSuccessors);
      break;
    }

    if (UsedAssumedInformation) {
      NewToBeExploredFrom.insert(I);
    } else if (AliveSuccessors.empty() ||
               (I->isTerminator() &&
                AliveSuccessors.size() < I->getNumSuccessors())) {
      if (KnownDeadEnds.insert(I))
        Change = ChangeStatus::CHANGED;
    }

    LLVM_DEBUG(dbgs() << "[AAIsDead] #AliveSuccessors: "
                      << AliveSuccessors.size() << " UsedAssumedInformation: "
                      << UsedAssumedInformation << "\n");

    for (const Instruction *AliveSuccessor : AliveSuccessors) {
      if (!I->isTerminator()) {
        assert(AliveSuccessors.size() == 1 &&
               "Non-terminator expected to have a single successor!");
        Worklist.push_back(AliveSuccessor);
      } else {
        // record the assumed live edge
        auto Edge = std::make_pair(I->getParent(), AliveSuccessor->getParent());
        if (AssumedLiveEdges.insert(Edge).second)
          Change = ChangeStatus::CHANGED;
        if (assumeLive(A, *AliveSuccessor->getParent()))
          Worklist.push_back(AliveSuccessor);
      }
    }
  }

  // Check if the content of ToBeExploredFrom changed, ignore the order.
  if (NewToBeExploredFrom.size() != ToBeExploredFrom.size() ||
      llvm::any_of(NewToBeExploredFrom, [&](const Instruction *I) {
        return !ToBeExploredFrom.count(I);
      })) {
    Change = ChangeStatus::CHANGED;
    ToBeExploredFrom = std::move(NewToBeExploredFrom);
  }

  // If we know everything is live there is no need to query for liveness.
  // Instead, indicating a pessimistic fixpoint will cause the state to be
  // "invalid" and all queries to be answered conservatively without lookups.
  // To be in this state we have to (1) finished the exploration and (3) not
  // discovered any non-trivial dead end and (2) not ruled unreachable code
  // dead.
  if (ToBeExploredFrom.empty() &&
      getAnchorScope()->size() == AssumedLiveBlocks.size() &&
      llvm::all_of(KnownDeadEnds, [](const Instruction *DeadEndI) {
        return DeadEndI->isTerminator() && DeadEndI->getNumSuccessors() == 0;
      }))
    return indicatePessimisticFixpoint();
  return Change;
}

/// Liveness information for a call sites.
struct AAIsDeadCallSite final : AAIsDeadFunction {
  AAIsDeadCallSite(const IRPosition &IRP, Attributor &A)
      : AAIsDeadFunction(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites instead of
    //       redirecting requests to the callee.
    llvm_unreachable("Abstract attributes for liveness are not "
                     "supported for call sites yet!");
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}
};
} // namespace

/// -------------------- Dereferenceable Argument Attribute --------------------

namespace {
struct AADereferenceableImpl : AADereferenceable {
  AADereferenceableImpl(const IRPosition &IRP, Attributor &A)
      : AADereferenceable(IRP, A) {}
  using StateType = DerefState;

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    Value &V = *getAssociatedValue().stripPointerCasts();
    SmallVector<Attribute, 4> Attrs;
    A.getAttrs(getIRPosition(),
               {Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
               Attrs, /* IgnoreSubsumingPositions */ false);
    for (const Attribute &Attr : Attrs)
      takeKnownDerefBytesMaximum(Attr.getValueAsInt());

    // Ensure we initialize the non-null AA (if necessary).
    bool IsKnownNonNull;
    AA::hasAssumedIRAttr<Attribute::NonNull>(
        A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNonNull);

    bool CanBeNull, CanBeFreed;
    takeKnownDerefBytesMaximum(V.getPointerDereferenceableBytes(
        A.getDataLayout(), CanBeNull, CanBeFreed));

    if (Instruction *CtxI = getCtxI())
      followUsesInMBEC(*this, A, getState(), *CtxI);
  }

  /// See AbstractAttribute::getState()
  /// {
  StateType &getState() override { return *this; }
  const StateType &getState() const override { return *this; }
  /// }

  /// Helper function for collecting accessed bytes in must-be-executed-context
  void addAccessedBytesForUse(Attributor &A, const Use *U, const Instruction *I,
                              DerefState &State) {
    const Value *UseV = U->get();
    if (!UseV->getType()->isPointerTy())
      return;

    std::optional<MemoryLocation> Loc = MemoryLocation::getOrNone(I);
    if (!Loc || Loc->Ptr != UseV || !Loc->Size.isPrecise() || I->isVolatile())
      return;

    int64_t Offset;
    const Value *Base = GetPointerBaseWithConstantOffset(
        Loc->Ptr, Offset, A.getDataLayout(), /*AllowNonInbounds*/ true);
    if (Base && Base == &getAssociatedValue())
      State.addAccessedBytes(Offset, Loc->Size.getValue());
  }

  /// See followUsesInMBEC
  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
                       AADereferenceable::StateType &State) {
    bool IsNonNull = false;
    bool TrackUse = false;
    int64_t DerefBytes = getKnownNonNullAndDerefBytesForUse(
        A, *this, getAssociatedValue(), U, I, IsNonNull, TrackUse);
    LLVM_DEBUG(dbgs() << "[AADereferenceable] Deref bytes: " << DerefBytes
                      << " for instruction " << *I << "\n");

    addAccessedBytesForUse(A, U, I, State);
    State.takeKnownDerefBytesMaximum(DerefBytes);
    return TrackUse;
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    ChangeStatus Change = AADereferenceable::manifest(A);
    bool IsKnownNonNull;
    bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
        A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
    if (IsAssumedNonNull &&
        A.hasAttr(getIRPosition(), Attribute::DereferenceableOrNull)) {
      A.removeAttrs(getIRPosition(), {Attribute::DereferenceableOrNull});
      return ChangeStatus::CHANGED;
    }
    return Change;
  }

  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    // TODO: Add *_globally support
    bool IsKnownNonNull;
    bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
        A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
    if (IsAssumedNonNull)
      Attrs.emplace_back(Attribute::getWithDereferenceableBytes(
          Ctx, getAssumedDereferenceableBytes()));
    else
      Attrs.emplace_back(Attribute::getWithDereferenceableOrNullBytes(
          Ctx, getAssumedDereferenceableBytes()));
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    if (!getAssumedDereferenceableBytes())
      return "unknown-dereferenceable";
    bool IsKnownNonNull;
    bool IsAssumedNonNull = false;
    if (A)
      IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
          *A, this, getIRPosition(), DepClassTy::NONE, IsKnownNonNull);
    return std::string("dereferenceable") +
           (IsAssumedNonNull ? "" : "_or_null") +
           (isAssumedGlobal() ? "_globally" : "") + "<" +
           std::to_string(getKnownDereferenceableBytes()) + "-" +
           std::to_string(getAssumedDereferenceableBytes()) + ">" +
           (!A ? " [non-null is unknown]" : "");
  }
};

/// Dereferenceable attribute for a floating value.
struct AADereferenceableFloating : AADereferenceableImpl {
  AADereferenceableFloating(const IRPosition &IRP, Attributor &A)
      : AADereferenceableImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    bool Stripped;
    bool UsedAssumedInformation = false;
    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
                                      AA::AnyScope, UsedAssumedInformation)) {
      Values.push_back({getAssociatedValue(), getCtxI()});
      Stripped = false;
    } else {
      Stripped = Values.size() != 1 ||
                 Values.front().getValue() != &getAssociatedValue();
    }

    const DataLayout &DL = A.getDataLayout();
    DerefState T;

    auto VisitValueCB = [&](const Value &V) -> bool {
      unsigned IdxWidth =
          DL.getIndexSizeInBits(V.getType()->getPointerAddressSpace());
      APInt Offset(IdxWidth, 0);
      const Value *Base = stripAndAccumulateOffsets(
          A, *this, &V, DL, Offset, /* GetMinOffset */ false,
          /* AllowNonInbounds */ true);

      const auto *AA = A.getAAFor<AADereferenceable>(
          *this, IRPosition::value(*Base), DepClassTy::REQUIRED);
      int64_t DerefBytes = 0;
      if (!AA || (!Stripped && this == AA)) {
        // Use IR information if we did not strip anything.
        // TODO: track globally.
        bool CanBeNull, CanBeFreed;
        DerefBytes =
            Base->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed);
        T.GlobalState.indicatePessimisticFixpoint();
      } else {
        const DerefState &DS = AA->getState();
        DerefBytes = DS.DerefBytesState.getAssumed();
        T.GlobalState &= DS.GlobalState;
      }

      // For now we do not try to "increase" dereferenceability due to negative
      // indices as we first have to come up with code to deal with loops and
      // for overflows of the dereferenceable bytes.
      int64_t OffsetSExt = Offset.getSExtValue();
      if (OffsetSExt < 0)
        OffsetSExt = 0;

      T.takeAssumedDerefBytesMinimum(
          std::max(int64_t(0), DerefBytes - OffsetSExt));

      if (this == AA) {
        if (!Stripped) {
          // If nothing was stripped IR information is all we got.
          T.takeKnownDerefBytesMaximum(
              std::max(int64_t(0), DerefBytes - OffsetSExt));
          T.indicatePessimisticFixpoint();
        } else if (OffsetSExt > 0) {
          // If something was stripped but there is circular reasoning we look
          // for the offset. If it is positive we basically decrease the
          // dereferenceable bytes in a circular loop now, which will simply
          // drive them down to the known value in a very slow way which we
          // can accelerate.
          T.indicatePessimisticFixpoint();
        }
      }

      return T.isValidState();
    };

    for (const auto &VAC : Values)
      if (!VisitValueCB(*VAC.getValue()))
        return indicatePessimisticFixpoint();

    return clampStateAndIndicateChange(getState(), T);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(dereferenceable)
  }
};

/// Dereferenceable attribute for a return value.
struct AADereferenceableReturned final
    : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {
  using Base =
      AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl>;
  AADereferenceableReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(dereferenceable)
  }
};

/// Dereferenceable attribute for an argument
struct AADereferenceableArgument final
    : AAArgumentFromCallSiteArguments<AADereferenceable,
                                      AADereferenceableImpl> {
  using Base =
      AAArgumentFromCallSiteArguments<AADereferenceable, AADereferenceableImpl>;
  AADereferenceableArgument(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(dereferenceable)
  }
};

/// Dereferenceable attribute for a call site argument.
struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {
  AADereferenceableCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AADereferenceableFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(dereferenceable)
  }
};

/// Dereferenceable attribute deduction for a call site return value.
struct AADereferenceableCallSiteReturned final
    : AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl> {
  using Base =
      AACallSiteReturnedFromReturned<AADereferenceable, AADereferenceableImpl>;
  AADereferenceableCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CS_ATTR(dereferenceable);
  }
};
} // namespace

// ------------------------ Align Argument Attribute ------------------------

namespace {
static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
                                    Value &AssociatedValue, const Use *U,
                                    const Instruction *I, bool &TrackUse) {
  // We need to follow common pointer manipulation uses to the accesses they
  // feed into.
  if (isa<CastInst>(I)) {
    // Follow all but ptr2int casts.
    TrackUse = !isa<PtrToIntInst>(I);
    return 0;
  }
  if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
    if (GEP->hasAllConstantIndices())
      TrackUse = true;
    return 0;
  }

  MaybeAlign MA;
  if (const auto *CB = dyn_cast<CallBase>(I)) {
    if (CB->isBundleOperand(U) || CB->isCallee(U))
      return 0;

    unsigned ArgNo = CB->getArgOperandNo(U);
    IRPosition IRP = IRPosition::callsite_argument(*CB, ArgNo);
    // As long as we only use known information there is no need to track
    // dependences here.
    auto *AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP, DepClassTy::NONE);
    if (AlignAA)
      MA = MaybeAlign(AlignAA->getKnownAlign());
  }

  const DataLayout &DL = A.getDataLayout();
  const Value *UseV = U->get();
  if (auto *SI = dyn_cast<StoreInst>(I)) {
    if (SI->getPointerOperand() == UseV)
      MA = SI->getAlign();
  } else if (auto *LI = dyn_cast<LoadInst>(I)) {
    if (LI->getPointerOperand() == UseV)
      MA = LI->getAlign();
  }

  if (!MA || *MA <= QueryingAA.getKnownAlign())
    return 0;

  unsigned Alignment = MA->value();
  int64_t Offset;

  if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
    if (Base == &AssociatedValue) {
      // BasePointerAddr + Offset = Alignment * Q for some integer Q.
      // So we can say that the maximum power of two which is a divisor of
      // gcd(Offset, Alignment) is an alignment.

      uint32_t gcd = std::gcd(uint32_t(abs((int32_t)Offset)), Alignment);
      Alignment = llvm::bit_floor(gcd);
    }
  }

  return Alignment;
}

struct AAAlignImpl : AAAlign {
  AAAlignImpl(const IRPosition &IRP, Attributor &A) : AAAlign(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    SmallVector<Attribute, 4> Attrs;
    A.getAttrs(getIRPosition(), {Attribute::Alignment}, Attrs);
    for (const Attribute &Attr : Attrs)
      takeKnownMaximum(Attr.getValueAsInt());

    Value &V = *getAssociatedValue().stripPointerCasts();
    takeKnownMaximum(V.getPointerAlignment(A.getDataLayout()).value());

    if (Instruction *CtxI = getCtxI())
      followUsesInMBEC(*this, A, getState(), *CtxI);
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    ChangeStatus LoadStoreChanged = ChangeStatus::UNCHANGED;

    // Check for users that allow alignment annotations.
    Value &AssociatedValue = getAssociatedValue();
    for (const Use &U : AssociatedValue.uses()) {
      if (auto *SI = dyn_cast<StoreInst>(U.getUser())) {
        if (SI->getPointerOperand() == &AssociatedValue)
          if (SI->getAlign() < getAssumedAlign()) {
            STATS_DECLTRACK(AAAlign, Store,
                            "Number of times alignment added to a store");
            SI->setAlignment(getAssumedAlign());
            LoadStoreChanged = ChangeStatus::CHANGED;
          }
      } else if (auto *LI = dyn_cast<LoadInst>(U.getUser())) {
        if (LI->getPointerOperand() == &AssociatedValue)
          if (LI->getAlign() < getAssumedAlign()) {
            LI->setAlignment(getAssumedAlign());
            STATS_DECLTRACK(AAAlign, Load,
                            "Number of times alignment added to a load");
            LoadStoreChanged = ChangeStatus::CHANGED;
          }
      }
    }

    ChangeStatus Changed = AAAlign::manifest(A);

    Align InheritAlign =
        getAssociatedValue().getPointerAlignment(A.getDataLayout());
    if (InheritAlign >= getAssumedAlign())
      return LoadStoreChanged;
    return Changed | LoadStoreChanged;
  }

  // TODO: Provide a helper to determine the implied ABI alignment and check in
  //       the existing manifest method and a new one for AAAlignImpl that value
  //       to avoid making the alignment explicit if it did not improve.

  /// See AbstractAttribute::getDeducedAttributes
  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    if (getAssumedAlign() > 1)
      Attrs.emplace_back(
          Attribute::getWithAlignment(Ctx, Align(getAssumedAlign())));
  }

  /// See followUsesInMBEC
  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
                       AAAlign::StateType &State) {
    bool TrackUse = false;

    unsigned int KnownAlign =
        getKnownAlignForUse(A, *this, getAssociatedValue(), U, I, TrackUse);
    State.takeKnownMaximum(KnownAlign);

    return TrackUse;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return "align<" + std::to_string(getKnownAlign().value()) + "-" +
           std::to_string(getAssumedAlign().value()) + ">";
  }
};

/// Align attribute for a floating value.
struct AAAlignFloating : AAAlignImpl {
  AAAlignFloating(const IRPosition &IRP, Attributor &A) : AAAlignImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    const DataLayout &DL = A.getDataLayout();

    bool Stripped;
    bool UsedAssumedInformation = false;
    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
                                      AA::AnyScope, UsedAssumedInformation)) {
      Values.push_back({getAssociatedValue(), getCtxI()});
      Stripped = false;
    } else {
      Stripped = Values.size() != 1 ||
                 Values.front().getValue() != &getAssociatedValue();
    }

    StateType T;
    auto VisitValueCB = [&](Value &V) -> bool {
      if (isa<UndefValue>(V) || isa<ConstantPointerNull>(V))
        return true;
      const auto *AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V),
                                           DepClassTy::REQUIRED);
      if (!AA || (!Stripped && this == AA)) {
        int64_t Offset;
        unsigned Alignment = 1;
        if (const Value *Base =
                GetPointerBaseWithConstantOffset(&V, Offset, DL)) {
          // TODO: Use AAAlign for the base too.
          Align PA = Base->getPointerAlignment(DL);
          // BasePointerAddr + Offset = Alignment * Q for some integer Q.
          // So we can say that the maximum power of two which is a divisor of
          // gcd(Offset, Alignment) is an alignment.

          uint32_t gcd =
              std::gcd(uint32_t(abs((int32_t)Offset)), uint32_t(PA.value()));
          Alignment = llvm::bit_floor(gcd);
        } else {
          Alignment = V.getPointerAlignment(DL).value();
        }
        // Use only IR information if we did not strip anything.
        T.takeKnownMaximum(Alignment);
        T.indicatePessimisticFixpoint();
      } else {
        // Use abstract attribute information.
        const AAAlign::StateType &DS = AA->getState();
        T ^= DS;
      }
      return T.isValidState();
    };

    for (const auto &VAC : Values) {
      if (!VisitValueCB(*VAC.getValue()))
        return indicatePessimisticFixpoint();
    }

    //  TODO: If we know we visited all incoming values, thus no are assumed
    //  dead, we can take the known information from the state T.
    return clampStateAndIndicateChange(getState(), T);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FLOATING_ATTR(align) }
};

/// Align attribute for function return value.
struct AAAlignReturned final
    : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {
  using Base = AAReturnedFromReturnedValues<AAAlign, AAAlignImpl>;
  AAAlignReturned(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(aligned) }
};

/// Align attribute for function argument.
struct AAAlignArgument final
    : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {
  using Base = AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl>;
  AAAlignArgument(const IRPosition &IRP, Attributor &A) : Base(IRP, A) {}

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // If the associated argument is involved in a must-tail call we give up
    // because we would need to keep the argument alignments of caller and
    // callee in-sync. Just does not seem worth the trouble right now.
    if (A.getInfoCache().isInvolvedInMustTailCall(*getAssociatedArgument()))
      return ChangeStatus::UNCHANGED;
    return Base::manifest(A);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(aligned) }
};

struct AAAlignCallSiteArgument final : AAAlignFloating {
  AAAlignCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAAlignFloating(IRP, A) {}

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // If the associated argument is involved in a must-tail call we give up
    // because we would need to keep the argument alignments of caller and
    // callee in-sync. Just does not seem worth the trouble right now.
    if (Argument *Arg = getAssociatedArgument())
      if (A.getInfoCache().isInvolvedInMustTailCall(*Arg))
        return ChangeStatus::UNCHANGED;
    ChangeStatus Changed = AAAlignImpl::manifest(A);
    Align InheritAlign =
        getAssociatedValue().getPointerAlignment(A.getDataLayout());
    if (InheritAlign >= getAssumedAlign())
      Changed = ChangeStatus::UNCHANGED;
    return Changed;
  }

  /// See AbstractAttribute::updateImpl(Attributor &A).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Changed = AAAlignFloating::updateImpl(A);
    if (Argument *Arg = getAssociatedArgument()) {
      // We only take known information from the argument
      // so we do not need to track a dependence.
      const auto *ArgAlignAA = A.getAAFor<AAAlign>(
          *this, IRPosition::argument(*Arg), DepClassTy::NONE);
      if (ArgAlignAA)
        takeKnownMaximum(ArgAlignAA->getKnownAlign().value());
    }
    return Changed;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(aligned) }
};

/// Align attribute deduction for a call site return value.
struct AAAlignCallSiteReturned final
    : AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl> {
  using Base = AACallSiteReturnedFromReturned<AAAlign, AAAlignImpl>;
  AAAlignCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(align); }
};
} // namespace

/// ------------------ Function No-Return Attribute ----------------------------
namespace {
struct AANoReturnImpl : public AANoReturn {
  AANoReturnImpl(const IRPosition &IRP, Attributor &A) : AANoReturn(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoReturn>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "noreturn" : "may-return";
  }

  /// See AbstractAttribute::updateImpl(Attributor &A).
  ChangeStatus updateImpl(Attributor &A) override {
    auto CheckForNoReturn = [](Instruction &) { return false; };
    bool UsedAssumedInformation = false;
    if (!A.checkForAllInstructions(CheckForNoReturn, *this,
                                   {(unsigned)Instruction::Ret},
                                   UsedAssumedInformation))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }
};

struct AANoReturnFunction final : AANoReturnImpl {
  AANoReturnFunction(const IRPosition &IRP, Attributor &A)
      : AANoReturnImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(noreturn) }
};

/// NoReturn attribute deduction for a call sites.
struct AANoReturnCallSite final : AANoReturnImpl {
  AANoReturnCallSite(const IRPosition &IRP, Attributor &A)
      : AANoReturnImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    bool IsKnownNoReturn;
    if (!AA::hasAssumedIRAttr<Attribute::NoReturn>(
            A, this, FnPos, DepClassTy::REQUIRED, IsKnownNoReturn))
      return indicatePessimisticFixpoint();
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(noreturn); }
};
} // namespace

/// ----------------------- Instance Info ---------------------------------

namespace {
/// A class to hold the state of for no-capture attributes.
struct AAInstanceInfoImpl : public AAInstanceInfo {
  AAInstanceInfoImpl(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfo(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    Value &V = getAssociatedValue();
    if (auto *C = dyn_cast<Constant>(&V)) {
      if (C->isThreadDependent())
        indicatePessimisticFixpoint();
      else
        indicateOptimisticFixpoint();
      return;
    }
    if (auto *CB = dyn_cast<CallBase>(&V))
      if (CB->arg_size() == 0 && !CB->mayHaveSideEffects() &&
          !CB->mayReadFromMemory()) {
        indicateOptimisticFixpoint();
        return;
      }
    if (auto *I = dyn_cast<Instruction>(&V)) {
      const auto *CI =
          A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
              *I->getFunction());
      if (mayBeInCycle(CI, I, /* HeaderOnly */ false)) {
        indicatePessimisticFixpoint();
        return;
      }
    }
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;

    Value &V = getAssociatedValue();
    const Function *Scope = nullptr;
    if (auto *I = dyn_cast<Instruction>(&V))
      Scope = I->getFunction();
    if (auto *A = dyn_cast<Argument>(&V)) {
      Scope = A->getParent();
      if (!Scope->hasLocalLinkage())
        return Changed;
    }
    if (!Scope)
      return indicateOptimisticFixpoint();

    bool IsKnownNoRecurse;
    if (AA::hasAssumedIRAttr<Attribute::NoRecurse>(
            A, this, IRPosition::function(*Scope), DepClassTy::OPTIONAL,
            IsKnownNoRecurse))
      return Changed;

    auto UsePred = [&](const Use &U, bool &Follow) {
      const Instruction *UserI = dyn_cast<Instruction>(U.getUser());
      if (!UserI || isa<GetElementPtrInst>(UserI) || isa<CastInst>(UserI) ||
          isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
        Follow = true;
        return true;
      }
      if (isa<LoadInst>(UserI) || isa<CmpInst>(UserI) ||
          (isa<StoreInst>(UserI) &&
           cast<StoreInst>(UserI)->getValueOperand() != U.get()))
        return true;
      if (auto *CB = dyn_cast<CallBase>(UserI)) {
        // This check is not guaranteeing uniqueness but for now that we cannot
        // end up with two versions of \p U thinking it was one.
        auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
        if (!Callee || !Callee->hasLocalLinkage())
          return true;
        if (!CB->isArgOperand(&U))
          return false;
        const auto *ArgInstanceInfoAA = A.getAAFor<AAInstanceInfo>(
            *this, IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U)),
            DepClassTy::OPTIONAL);
        if (!ArgInstanceInfoAA ||
            !ArgInstanceInfoAA->isAssumedUniqueForAnalysis())
          return false;
        // If this call base might reach the scope again we might forward the
        // argument back here. This is very conservative.
        if (AA::isPotentiallyReachable(
                A, *CB, *Scope, *this, /* ExclusionSet */ nullptr,
                [Scope](const Function &Fn) { return &Fn != Scope; }))
          return false;
        return true;
      }
      return false;
    };

    auto EquivalentUseCB = [&](const Use &OldU, const Use &NewU) {
      if (auto *SI = dyn_cast<StoreInst>(OldU.getUser())) {
        auto *Ptr = SI->getPointerOperand()->stripPointerCasts();
        if ((isa<AllocaInst>(Ptr) || isNoAliasCall(Ptr)) &&
            AA::isDynamicallyUnique(A, *this, *Ptr))
          return true;
      }
      return false;
    };

    if (!A.checkForAllUses(UsePred, *this, V, /* CheckBBLivenessOnly */ true,
                           DepClassTy::OPTIONAL,
                           /* IgnoreDroppableUses */ true, EquivalentUseCB))
      return indicatePessimisticFixpoint();

    return Changed;
  }

  /// See AbstractState::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return isAssumedUniqueForAnalysis() ? "<unique [fAa]>" : "<unknown>";
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}
};

/// InstanceInfo attribute for floating values.
struct AAInstanceInfoFloating : AAInstanceInfoImpl {
  AAInstanceInfoFloating(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfoImpl(IRP, A) {}
};

/// NoCapture attribute for function arguments.
struct AAInstanceInfoArgument final : AAInstanceInfoFloating {
  AAInstanceInfoArgument(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfoFloating(IRP, A) {}
};

/// InstanceInfo attribute for call site arguments.
struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {
  AAInstanceInfoCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfoImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    if (!Arg)
      return indicatePessimisticFixpoint();
    const IRPosition &ArgPos = IRPosition::argument(*Arg);
    auto *ArgAA =
        A.getAAFor<AAInstanceInfo>(*this, ArgPos, DepClassTy::REQUIRED);
    if (!ArgAA)
      return indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(getState(), ArgAA->getState());
  }
};

/// InstanceInfo attribute for function return value.
struct AAInstanceInfoReturned final : AAInstanceInfoImpl {
  AAInstanceInfoReturned(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfoImpl(IRP, A) {
    llvm_unreachable("InstanceInfo is not applicable to function returns!");
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    llvm_unreachable("InstanceInfo is not applicable to function returns!");
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("InstanceInfo is not applicable to function returns!");
  }
};

/// InstanceInfo attribute deduction for a call site return value.
struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {
  AAInstanceInfoCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAInstanceInfoFloating(IRP, A) {}
};
} // namespace

/// ----------------------- Variable Capturing ---------------------------------
bool AANoCapture::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                                Attribute::AttrKind ImpliedAttributeKind,
                                bool IgnoreSubsumingPositions) {
  assert(ImpliedAttributeKind == Attribute::NoCapture &&
         "Unexpected attribute kind");
  Value &V = IRP.getAssociatedValue();
  if (!IRP.isArgumentPosition())
    return V.use_empty();

  // You cannot "capture" null in the default address space.
  if (isa<UndefValue>(V) || (isa<ConstantPointerNull>(V) &&
                             V.getType()->getPointerAddressSpace() == 0)) {
    return true;
  }

  if (A.hasAttr(IRP, {Attribute::NoCapture},
                /* IgnoreSubsumingPositions */ true, Attribute::NoCapture))
    return true;

  if (IRP.getPositionKind() == IRP_CALL_SITE_ARGUMENT)
    if (Argument *Arg = IRP.getAssociatedArgument())
      if (A.hasAttr(IRPosition::argument(*Arg),
                    {Attribute::NoCapture, Attribute::ByVal},
                    /* IgnoreSubsumingPositions */ true)) {
        A.manifestAttrs(IRP,
                        Attribute::get(V.getContext(), Attribute::NoCapture));
        return true;
      }

  if (const Function *F = IRP.getAssociatedFunction()) {
    // Check what state the associated function can actually capture.
    AANoCapture::StateType State;
    determineFunctionCaptureCapabilities(IRP, *F, State);
    if (State.isKnown(NO_CAPTURE)) {
      A.manifestAttrs(IRP,
                      Attribute::get(V.getContext(), Attribute::NoCapture));
      return true;
    }
  }

  return false;
}

/// Set the NOT_CAPTURED_IN_MEM and NOT_CAPTURED_IN_RET bits in \p Known
/// depending on the ability of the function associated with \p IRP to capture
/// state in memory and through "returning/throwing", respectively.
void AANoCapture::determineFunctionCaptureCapabilities(const IRPosition &IRP,
                                                       const Function &F,
                                                       BitIntegerState &State) {
  // TODO: Once we have memory behavior attributes we should use them here.

  // If we know we cannot communicate or write to memory, we do not care about
  // ptr2int anymore.
  bool ReadOnly = F.onlyReadsMemory();
  bool NoThrow = F.doesNotThrow();
  bool IsVoidReturn = F.getReturnType()->isVoidTy();
  if (ReadOnly && NoThrow && IsVoidReturn) {
    State.addKnownBits(NO_CAPTURE);
    return;
  }

  // A function cannot capture state in memory if it only reads memory, it can
  // however return/throw state and the state might be influenced by the
  // pointer value, e.g., loading from a returned pointer might reveal a bit.
  if (ReadOnly)
    State.addKnownBits(NOT_CAPTURED_IN_MEM);

  // A function cannot communicate state back if it does not through
  // exceptions and doesn not return values.
  if (NoThrow && IsVoidReturn)
    State.addKnownBits(NOT_CAPTURED_IN_RET);

  // Check existing "returned" attributes.
  int ArgNo = IRP.getCalleeArgNo();
  if (!NoThrow || ArgNo < 0 ||
      !F.getAttributes().hasAttrSomewhere(Attribute::Returned))
    return;

  for (unsigned U = 0, E = F.arg_size(); U < E; ++U)
    if (F.hasParamAttribute(U, Attribute::Returned)) {
      if (U == unsigned(ArgNo))
        State.removeAssumedBits(NOT_CAPTURED_IN_RET);
      else if (ReadOnly)
        State.addKnownBits(NO_CAPTURE);
      else
        State.addKnownBits(NOT_CAPTURED_IN_RET);
      break;
    }
}

namespace {
/// A class to hold the state of for no-capture attributes.
struct AANoCaptureImpl : public AANoCapture {
  AANoCaptureImpl(const IRPosition &IRP, Attributor &A) : AANoCapture(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    bool IsKnown;
    assert(!AA::hasAssumedIRAttr<Attribute::NoCapture>(
        A, nullptr, getIRPosition(), DepClassTy::NONE, IsKnown));
    (void)IsKnown;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override;

  /// see AbstractAttribute::isAssumedNoCaptureMaybeReturned(...).
  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    if (!isAssumedNoCaptureMaybeReturned())
      return;

    if (isArgumentPosition()) {
      if (isAssumedNoCapture())
        Attrs.emplace_back(Attribute::get(Ctx, Attribute::NoCapture));
      else if (ManifestInternal)
        Attrs.emplace_back(Attribute::get(Ctx, "no-capture-maybe-returned"));
    }
  }

  /// See AbstractState::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    if (isKnownNoCapture())
      return "known not-captured";
    if (isAssumedNoCapture())
      return "assumed not-captured";
    if (isKnownNoCaptureMaybeReturned())
      return "known not-captured-maybe-returned";
    if (isAssumedNoCaptureMaybeReturned())
      return "assumed not-captured-maybe-returned";
    return "assumed-captured";
  }

  /// Check the use \p U and update \p State accordingly. Return true if we
  /// should continue to update the state.
  bool checkUse(Attributor &A, AANoCapture::StateType &State, const Use &U,
                bool &Follow) {
    Instruction *UInst = cast<Instruction>(U.getUser());
    LLVM_DEBUG(dbgs() << "[AANoCapture] Check use: " << *U.get() << " in "
                      << *UInst << "\n");

    // Deal with ptr2int by following uses.
    if (isa<PtrToIntInst>(UInst)) {
      LLVM_DEBUG(dbgs() << " - ptr2int assume the worst!\n");
      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
                          /* Return */ true);
    }

    // For stores we already checked if we can follow them, if they make it
    // here we give up.
    if (isa<StoreInst>(UInst))
      return isCapturedIn(State, /* Memory */ true, /* Integer */ false,
                          /* Return */ false);

    // Explicitly catch return instructions.
    if (isa<ReturnInst>(UInst)) {
      if (UInst->getFunction() == getAnchorScope())
        return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
                            /* Return */ true);
      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
                          /* Return */ true);
    }

    // For now we only use special logic for call sites. However, the tracker
    // itself knows about a lot of other non-capturing cases already.
    auto *CB = dyn_cast<CallBase>(UInst);
    if (!CB || !CB->isArgOperand(&U))
      return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
                          /* Return */ true);

    unsigned ArgNo = CB->getArgOperandNo(&U);
    const IRPosition &CSArgPos = IRPosition::callsite_argument(*CB, ArgNo);
    // If we have a abstract no-capture attribute for the argument we can use
    // it to justify a non-capture attribute here. This allows recursion!
    bool IsKnownNoCapture;
    const AANoCapture *ArgNoCaptureAA = nullptr;
    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
        A, this, CSArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
        &ArgNoCaptureAA);
    if (IsAssumedNoCapture)
      return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
                          /* Return */ false);
    if (ArgNoCaptureAA && ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned()) {
      Follow = true;
      return isCapturedIn(State, /* Memory */ false, /* Integer */ false,
                          /* Return */ false);
    }

    // Lastly, we could not find a reason no-capture can be assumed so we don't.
    return isCapturedIn(State, /* Memory */ true, /* Integer */ true,
                        /* Return */ true);
  }

  /// Update \p State according to \p CapturedInMem, \p CapturedInInt, and
  /// \p CapturedInRet, then return true if we should continue updating the
  /// state.
  static bool isCapturedIn(AANoCapture::StateType &State, bool CapturedInMem,
                           bool CapturedInInt, bool CapturedInRet) {
    LLVM_DEBUG(dbgs() << " - captures [Mem " << CapturedInMem << "|Int "
                      << CapturedInInt << "|Ret " << CapturedInRet << "]\n");
    if (CapturedInMem)
      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_MEM);
    if (CapturedInInt)
      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_INT);
    if (CapturedInRet)
      State.removeAssumedBits(AANoCapture::NOT_CAPTURED_IN_RET);
    return State.isAssumed(AANoCapture::NO_CAPTURE_MAYBE_RETURNED);
  }
};

ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
  const IRPosition &IRP = getIRPosition();
  Value *V = isArgumentPosition() ? IRP.getAssociatedArgument()
                                  : &IRP.getAssociatedValue();
  if (!V)
    return indicatePessimisticFixpoint();

  const Function *F =
      isArgumentPosition() ? IRP.getAssociatedFunction() : IRP.getAnchorScope();
  assert(F && "Expected a function!");
  const IRPosition &FnPos = IRPosition::function(*F);

  AANoCapture::StateType T;

  // Readonly means we cannot capture through memory.
  bool IsKnown;
  if (AA::isAssumedReadOnly(A, FnPos, *this, IsKnown)) {
    T.addKnownBits(NOT_CAPTURED_IN_MEM);
    if (IsKnown)
      addKnownBits(NOT_CAPTURED_IN_MEM);
  }

  // Make sure all returned values are different than the underlying value.
  // TODO: we could do this in a more sophisticated way inside
  //       AAReturnedValues, e.g., track all values that escape through returns
  //       directly somehow.
  auto CheckReturnedArgs = [&](bool &UsedAssumedInformation) {
    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(IRPosition::returned(*F), this, Values,
                                      AA::ValueScope::Intraprocedural,
                                      UsedAssumedInformation))
      return false;
    bool SeenConstant = false;
    for (const AA::ValueAndContext &VAC : Values) {
      if (isa<Constant>(VAC.getValue())) {
        if (SeenConstant)
          return false;
        SeenConstant = true;
      } else if (!isa<Argument>(VAC.getValue()) ||
                 VAC.getValue() == getAssociatedArgument())
        return false;
    }
    return true;
  };

  bool IsKnownNoUnwind;
  if (AA::hasAssumedIRAttr<Attribute::NoUnwind>(
          A, this, FnPos, DepClassTy::OPTIONAL, IsKnownNoUnwind)) {
    bool IsVoidTy = F->getReturnType()->isVoidTy();
    bool UsedAssumedInformation = false;
    if (IsVoidTy || CheckReturnedArgs(UsedAssumedInformation)) {
      T.addKnownBits(NOT_CAPTURED_IN_RET);
      if (T.isKnown(NOT_CAPTURED_IN_MEM))
        return ChangeStatus::UNCHANGED;
      if (IsKnownNoUnwind && (IsVoidTy || !UsedAssumedInformation)) {
        addKnownBits(NOT_CAPTURED_IN_RET);
        if (isKnown(NOT_CAPTURED_IN_MEM))
          return indicateOptimisticFixpoint();
      }
    }
  }

  auto IsDereferenceableOrNull = [&](Value *O, const DataLayout &DL) {
    const auto *DerefAA = A.getAAFor<AADereferenceable>(
        *this, IRPosition::value(*O), DepClassTy::OPTIONAL);
    return DerefAA && DerefAA->getAssumedDereferenceableBytes();
  };

  auto UseCheck = [&](const Use &U, bool &Follow) -> bool {
    switch (DetermineUseCaptureKind(U, IsDereferenceableOrNull)) {
    case UseCaptureKind::NO_CAPTURE:
      return true;
    case UseCaptureKind::MAY_CAPTURE:
      return checkUse(A, T, U, Follow);
    case UseCaptureKind::PASSTHROUGH:
      Follow = true;
      return true;
    }
    llvm_unreachable("Unexpected use capture kind!");
  };

  if (!A.checkForAllUses(UseCheck, *this, *V))
    return indicatePessimisticFixpoint();

  AANoCapture::StateType &S = getState();
  auto Assumed = S.getAssumed();
  S.intersectAssumedBits(T.getAssumed());
  if (!isAssumedNoCaptureMaybeReturned())
    return indicatePessimisticFixpoint();
  return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
                                   : ChangeStatus::CHANGED;
}

/// NoCapture attribute for function arguments.
struct AANoCaptureArgument final : AANoCaptureImpl {
  AANoCaptureArgument(const IRPosition &IRP, Attributor &A)
      : AANoCaptureImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nocapture) }
};

/// NoCapture attribute for call site arguments.
struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {
  AANoCaptureCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANoCaptureImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    if (!Arg)
      return indicatePessimisticFixpoint();
    const IRPosition &ArgPos = IRPosition::argument(*Arg);
    bool IsKnownNoCapture;
    const AANoCapture *ArgAA = nullptr;
    if (AA::hasAssumedIRAttr<Attribute::NoCapture>(
            A, this, ArgPos, DepClassTy::REQUIRED, IsKnownNoCapture, false,
            &ArgAA))
      return ChangeStatus::UNCHANGED;
    if (!ArgAA || !ArgAA->isAssumedNoCaptureMaybeReturned())
      return indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(getState(), ArgAA->getState());
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override{STATS_DECLTRACK_CSARG_ATTR(nocapture)};
};

/// NoCapture attribute for floating values.
struct AANoCaptureFloating final : AANoCaptureImpl {
  AANoCaptureFloating(const IRPosition &IRP, Attributor &A)
      : AANoCaptureImpl(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(nocapture)
  }
};

/// NoCapture attribute for function return value.
struct AANoCaptureReturned final : AANoCaptureImpl {
  AANoCaptureReturned(const IRPosition &IRP, Attributor &A)
      : AANoCaptureImpl(IRP, A) {
    llvm_unreachable("NoCapture is not applicable to function returns!");
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    llvm_unreachable("NoCapture is not applicable to function returns!");
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("NoCapture is not applicable to function returns!");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}
};

/// NoCapture attribute deduction for a call site return value.
struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {
  AANoCaptureCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AANoCaptureImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    const Function *F = getAnchorScope();
    // Check what state the associated function can actually capture.
    determineFunctionCaptureCapabilities(getIRPosition(), *F, *this);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(nocapture)
  }
};
} // namespace

/// ------------------ Value Simplify Attribute ----------------------------

bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {
  // FIXME: Add a typecast support.
  SimplifiedAssociatedValue = AA::combineOptionalValuesInAAValueLatice(
      SimplifiedAssociatedValue, Other, Ty);
  if (SimplifiedAssociatedValue == std::optional<Value *>(nullptr))
    return false;

  LLVM_DEBUG({
    if (SimplifiedAssociatedValue)
      dbgs() << "[ValueSimplify] is assumed to be "
             << **SimplifiedAssociatedValue << "\n";
    else
      dbgs() << "[ValueSimplify] is assumed to be <none>\n";
  });
  return true;
}

namespace {
struct AAValueSimplifyImpl : AAValueSimplify {
  AAValueSimplifyImpl(const IRPosition &IRP, Attributor &A)
      : AAValueSimplify(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    if (getAssociatedValue().getType()->isVoidTy())
      indicatePessimisticFixpoint();
    if (A.hasSimplificationCallback(getIRPosition()))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    LLVM_DEBUG({
      dbgs() << "SAV: " << (bool)SimplifiedAssociatedValue << " ";
      if (SimplifiedAssociatedValue && *SimplifiedAssociatedValue)
        dbgs() << "SAV: " << **SimplifiedAssociatedValue << " ";
    });
    return isValidState() ? (isAtFixpoint() ? "simplified" : "maybe-simple")
                          : "not-simple";
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}

  /// See AAValueSimplify::getAssumedSimplifiedValue()
  std::optional<Value *>
  getAssumedSimplifiedValue(Attributor &A) const override {
    return SimplifiedAssociatedValue;
  }

  /// Ensure the return value is \p V with type \p Ty, if not possible return
  /// nullptr. If \p Check is true we will only verify such an operation would
  /// suceed and return a non-nullptr value if that is the case. No IR is
  /// generated or modified.
  static Value *ensureType(Attributor &A, Value &V, Type &Ty, Instruction *CtxI,
                           bool Check) {
    if (auto *TypedV = AA::getWithType(V, Ty))
      return TypedV;
    if (CtxI && V.getType()->canLosslesslyBitCastTo(&Ty))
      return Check ? &V
                   : BitCastInst::CreatePointerBitCastOrAddrSpaceCast(&V, &Ty,
                                                                      "", CtxI);
    return nullptr;
  }

  /// Reproduce \p I with type \p Ty or return nullptr if that is not posisble.
  /// If \p Check is true we will only verify such an operation would suceed and
  /// return a non-nullptr value if that is the case. No IR is generated or
  /// modified.
  static Value *reproduceInst(Attributor &A,
                              const AbstractAttribute &QueryingAA,
                              Instruction &I, Type &Ty, Instruction *CtxI,
                              bool Check, ValueToValueMapTy &VMap) {
    assert(CtxI && "Cannot reproduce an instruction without context!");
    if (Check && (I.mayReadFromMemory() ||
                  !isSafeToSpeculativelyExecute(&I, CtxI, /* DT */ nullptr,
                                                /* TLI */ nullptr)))
      return nullptr;
    for (Value *Op : I.operands()) {
      Value *NewOp = reproduceValue(A, QueryingAA, *Op, Ty, CtxI, Check, VMap);
      if (!NewOp) {
        assert(Check && "Manifest of new value unexpectedly failed!");
        return nullptr;
      }
      if (!Check)
        VMap[Op] = NewOp;
    }
    if (Check)
      return &I;

    Instruction *CloneI = I.clone();
    // TODO: Try to salvage debug information here.
    CloneI->setDebugLoc(DebugLoc());
    VMap[&I] = CloneI;
    CloneI->insertBefore(CtxI);
    RemapInstruction(CloneI, VMap);
    return CloneI;
  }

  /// Reproduce \p V with type \p Ty or return nullptr if that is not posisble.
  /// If \p Check is true we will only verify such an operation would suceed and
  /// return a non-nullptr value if that is the case. No IR is generated or
  /// modified.
  static Value *reproduceValue(Attributor &A,
                               const AbstractAttribute &QueryingAA, Value &V,
                               Type &Ty, Instruction *CtxI, bool Check,
                               ValueToValueMapTy &VMap) {
    if (const auto &NewV = VMap.lookup(&V))
      return NewV;
    bool UsedAssumedInformation = false;
    std::optional<Value *> SimpleV = A.getAssumedSimplified(
        V, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
    if (!SimpleV.has_value())
      return PoisonValue::get(&Ty);
    Value *EffectiveV = &V;
    if (*SimpleV)
      EffectiveV = *SimpleV;
    if (auto *C = dyn_cast<Constant>(EffectiveV))
      return C;
    if (CtxI && AA::isValidAtPosition(AA::ValueAndContext(*EffectiveV, *CtxI),
                                      A.getInfoCache()))
      return ensureType(A, *EffectiveV, Ty, CtxI, Check);
    if (auto *I = dyn_cast<Instruction>(EffectiveV))
      if (Value *NewV = reproduceInst(A, QueryingAA, *I, Ty, CtxI, Check, VMap))
        return ensureType(A, *NewV, Ty, CtxI, Check);
    return nullptr;
  }

  /// Return a value we can use as replacement for the associated one, or
  /// nullptr if we don't have one that makes sense.
  Value *manifestReplacementValue(Attributor &A, Instruction *CtxI) const {
    Value *NewV = SimplifiedAssociatedValue
                      ? *SimplifiedAssociatedValue
                      : UndefValue::get(getAssociatedType());
    if (NewV && NewV != &getAssociatedValue()) {
      ValueToValueMapTy VMap;
      // First verify we can reprduce the value with the required type at the
      // context location before we actually start modifying the IR.
      if (reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
                         /* CheckOnly */ true, VMap))
        return reproduceValue(A, *this, *NewV, *getAssociatedType(), CtxI,
                              /* CheckOnly */ false, VMap);
    }
    return nullptr;
  }

  /// Helper function for querying AAValueSimplify and updating candidate.
  /// \param IRP The value position we are trying to unify with SimplifiedValue
  bool checkAndUpdate(Attributor &A, const AbstractAttribute &QueryingAA,
                      const IRPosition &IRP, bool Simplify = true) {
    bool UsedAssumedInformation = false;
    std::optional<Value *> QueryingValueSimplified = &IRP.getAssociatedValue();
    if (Simplify)
      QueryingValueSimplified = A.getAssumedSimplified(
          IRP, QueryingAA, UsedAssumedInformation, AA::Interprocedural);
    return unionAssumed(QueryingValueSimplified);
  }

  /// Returns a candidate is found or not
  template <typename AAType> bool askSimplifiedValueFor(Attributor &A) {
    if (!getAssociatedValue().getType()->isIntegerTy())
      return false;

    // This will also pass the call base context.
    const auto *AA =
        A.getAAFor<AAType>(*this, getIRPosition(), DepClassTy::NONE);
    if (!AA)
      return false;

    std::optional<Constant *> COpt = AA->getAssumedConstant(A);

    if (!COpt) {
      SimplifiedAssociatedValue = std::nullopt;
      A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
      return true;
    }
    if (auto *C = *COpt) {
      SimplifiedAssociatedValue = C;
      A.recordDependence(*AA, *this, DepClassTy::OPTIONAL);
      return true;
    }
    return false;
  }

  bool askSimplifiedValueForOtherAAs(Attributor &A) {
    if (askSimplifiedValueFor<AAValueConstantRange>(A))
      return true;
    if (askSimplifiedValueFor<AAPotentialConstantValues>(A))
      return true;
    return false;
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    for (auto &U : getAssociatedValue().uses()) {
      // Check if we need to adjust the insertion point to make sure the IR is
      // valid.
      Instruction *IP = dyn_cast<Instruction>(U.getUser());
      if (auto *PHI = dyn_cast_or_null<PHINode>(IP))
        IP = PHI->getIncomingBlock(U)->getTerminator();
      if (auto *NewV = manifestReplacementValue(A, IP)) {
        LLVM_DEBUG(dbgs() << "[ValueSimplify] " << getAssociatedValue()
                          << " -> " << *NewV << " :: " << *this << "\n");
        if (A.changeUseAfterManifest(U, *NewV))
          Changed = ChangeStatus::CHANGED;
      }
    }

    return Changed | AAValueSimplify::manifest(A);
  }

  /// See AbstractState::indicatePessimisticFixpoint(...).
  ChangeStatus indicatePessimisticFixpoint() override {
    SimplifiedAssociatedValue = &getAssociatedValue();
    return AAValueSimplify::indicatePessimisticFixpoint();
  }
};

struct AAValueSimplifyArgument final : AAValueSimplifyImpl {
  AAValueSimplifyArgument(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyImpl(IRP, A) {}

  void initialize(Attributor &A) override {
    AAValueSimplifyImpl::initialize(A);
    if (A.hasAttr(getIRPosition(),
                  {Attribute::InAlloca, Attribute::Preallocated,
                   Attribute::StructRet, Attribute::Nest, Attribute::ByVal},
                  /* IgnoreSubsumingPositions */ true))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // Byval is only replacable if it is readonly otherwise we would write into
    // the replaced value and not the copy that byval creates implicitly.
    Argument *Arg = getAssociatedArgument();
    if (Arg->hasByValAttr()) {
      // TODO: We probably need to verify synchronization is not an issue, e.g.,
      //       there is no race by not copying a constant byval.
      bool IsKnown;
      if (!AA::isAssumedReadOnly(A, getIRPosition(), *this, IsKnown))
        return indicatePessimisticFixpoint();
    }

    auto Before = SimplifiedAssociatedValue;

    auto PredForCallSite = [&](AbstractCallSite ACS) {
      const IRPosition &ACSArgPos =
          IRPosition::callsite_argument(ACS, getCallSiteArgNo());
      // Check if a coresponding argument was found or if it is on not
      // associated (which can happen for callback calls).
      if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
        return false;

      // Simplify the argument operand explicitly and check if the result is
      // valid in the current scope. This avoids refering to simplified values
      // in other functions, e.g., we don't want to say a an argument in a
      // static function is actually an argument in a different function.
      bool UsedAssumedInformation = false;
      std::optional<Constant *> SimpleArgOp =
          A.getAssumedConstant(ACSArgPos, *this, UsedAssumedInformation);
      if (!SimpleArgOp)
        return true;
      if (!*SimpleArgOp)
        return false;
      if (!AA::isDynamicallyUnique(A, *this, **SimpleArgOp))
        return false;
      return unionAssumed(*SimpleArgOp);
    };

    // Generate a answer specific to a call site context.
    bool Success;
    bool UsedAssumedInformation = false;
    if (hasCallBaseContext() &&
        getCallBaseContext()->getCalledOperand() == Arg->getParent())
      Success = PredForCallSite(
          AbstractCallSite(&getCallBaseContext()->getCalledOperandUse()));
    else
      Success = A.checkForAllCallSites(PredForCallSite, *this, true,
                                       UsedAssumedInformation);

    if (!Success)
      if (!askSimplifiedValueForOtherAAs(A))
        return indicatePessimisticFixpoint();

    // If a candidate was found in this update, return CHANGED.
    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
                                               : ChangeStatus ::CHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(value_simplify)
  }
};

struct AAValueSimplifyReturned : AAValueSimplifyImpl {
  AAValueSimplifyReturned(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyImpl(IRP, A) {}

  /// See AAValueSimplify::getAssumedSimplifiedValue()
  std::optional<Value *>
  getAssumedSimplifiedValue(Attributor &A) const override {
    if (!isValidState())
      return nullptr;
    return SimplifiedAssociatedValue;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto Before = SimplifiedAssociatedValue;

    auto ReturnInstCB = [&](Instruction &I) {
      auto &RI = cast<ReturnInst>(I);
      return checkAndUpdate(
          A, *this,
          IRPosition::value(*RI.getReturnValue(), getCallBaseContext()));
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllInstructions(ReturnInstCB, *this, {Instruction::Ret},
                                   UsedAssumedInformation))
      if (!askSimplifiedValueForOtherAAs(A))
        return indicatePessimisticFixpoint();

    // If a candidate was found in this update, return CHANGED.
    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
                                               : ChangeStatus ::CHANGED;
  }

  ChangeStatus manifest(Attributor &A) override {
    // We queried AAValueSimplify for the returned values so they will be
    // replaced if a simplified form was found. Nothing to do here.
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(value_simplify)
  }
};

struct AAValueSimplifyFloating : AAValueSimplifyImpl {
  AAValueSimplifyFloating(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAValueSimplifyImpl::initialize(A);
    Value &V = getAnchorValue();

    // TODO: add other stuffs
    if (isa<Constant>(V))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto Before = SimplifiedAssociatedValue;
    if (!askSimplifiedValueForOtherAAs(A))
      return indicatePessimisticFixpoint();

    // If a candidate was found in this update, return CHANGED.
    return Before == SimplifiedAssociatedValue ? ChangeStatus::UNCHANGED
                                               : ChangeStatus ::CHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(value_simplify)
  }
};

struct AAValueSimplifyFunction : AAValueSimplifyImpl {
  AAValueSimplifyFunction(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    SimplifiedAssociatedValue = nullptr;
    indicateOptimisticFixpoint();
  }
  /// See AbstractAttribute::initialize(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable(
        "AAValueSimplify(Function|CallSite)::updateImpl will not be called");
  }
  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FN_ATTR(value_simplify)
  }
};

struct AAValueSimplifyCallSite : AAValueSimplifyFunction {
  AAValueSimplifyCallSite(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyFunction(IRP, A) {}
  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CS_ATTR(value_simplify)
  }
};

struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {
  AAValueSimplifyCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyImpl(IRP, A) {}

  void initialize(Attributor &A) override {
    AAValueSimplifyImpl::initialize(A);
    Function *Fn = getAssociatedFunction();
    assert(Fn && "Did expect an associted function");
    for (Argument &Arg : Fn->args()) {
      if (Arg.hasReturnedAttr()) {
        auto IRP = IRPosition::callsite_argument(*cast<CallBase>(getCtxI()),
                                                 Arg.getArgNo());
        if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_ARGUMENT &&
            checkAndUpdate(A, *this, IRP))
          indicateOptimisticFixpoint();
        else
          indicatePessimisticFixpoint();
        return;
      }
    }
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
        return indicatePessimisticFixpoint();
  }

  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(value_simplify)
  }
};

struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {
  AAValueSimplifyCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAValueSimplifyFloating(IRP, A) {}

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    // TODO: We should avoid simplification duplication to begin with.
    auto *FloatAA = A.lookupAAFor<AAValueSimplify>(
        IRPosition::value(getAssociatedValue()), this, DepClassTy::NONE);
    if (FloatAA && FloatAA->getState().isValidState())
      return Changed;

    if (auto *NewV = manifestReplacementValue(A, getCtxI())) {
      Use &U = cast<CallBase>(&getAnchorValue())
                   ->getArgOperandUse(getCallSiteArgNo());
      if (A.changeUseAfterManifest(U, *NewV))
        Changed = ChangeStatus::CHANGED;
    }

    return Changed | AAValueSimplify::manifest(A);
  }

  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(value_simplify)
  }
};
} // namespace

/// ----------------------- Heap-To-Stack Conversion ---------------------------
namespace {
struct AAHeapToStackFunction final : public AAHeapToStack {

  struct AllocationInfo {
    /// The call that allocates the memory.
    CallBase *const CB;

    /// The library function id for the allocation.
    LibFunc LibraryFunctionId = NotLibFunc;

    /// The status wrt. a rewrite.
    enum {
      STACK_DUE_TO_USE,
      STACK_DUE_TO_FREE,
      INVALID,
    } Status = STACK_DUE_TO_USE;

    /// Flag to indicate if we encountered a use that might free this allocation
    /// but which is not in the deallocation infos.
    bool HasPotentiallyFreeingUnknownUses = false;

    /// Flag to indicate that we should place the new alloca in the function
    /// entry block rather than where the call site (CB) is.
    bool MoveAllocaIntoEntry = true;

    /// The set of free calls that use this allocation.
    SmallSetVector<CallBase *, 1> PotentialFreeCalls{};
  };

  struct DeallocationInfo {
    /// The call that deallocates the memory.
    CallBase *const CB;
    /// The value freed by the call.
    Value *FreedOp;

    /// Flag to indicate if we don't know all objects this deallocation might
    /// free.
    bool MightFreeUnknownObjects = false;

    /// The set of allocation calls that are potentially freed.
    SmallSetVector<CallBase *, 1> PotentialAllocationCalls{};
  };

  AAHeapToStackFunction(const IRPosition &IRP, Attributor &A)
      : AAHeapToStack(IRP, A) {}

  ~AAHeapToStackFunction() {
    // Ensure we call the destructor so we release any memory allocated in the
    // sets.
    for (auto &It : AllocationInfos)
      It.second->~AllocationInfo();
    for (auto &It : DeallocationInfos)
      It.second->~DeallocationInfo();
  }

  void initialize(Attributor &A) override {
    AAHeapToStack::initialize(A);

    const Function *F = getAnchorScope();
    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);

    auto AllocationIdentifierCB = [&](Instruction &I) {
      CallBase *CB = dyn_cast<CallBase>(&I);
      if (!CB)
        return true;
      if (Value *FreedOp = getFreedOperand(CB, TLI)) {
        DeallocationInfos[CB] = new (A.Allocator) DeallocationInfo{CB, FreedOp};
        return true;
      }
      // To do heap to stack, we need to know that the allocation itself is
      // removable once uses are rewritten, and that we can initialize the
      // alloca to the same pattern as the original allocation result.
      if (isRemovableAlloc(CB, TLI)) {
        auto *I8Ty = Type::getInt8Ty(CB->getParent()->getContext());
        if (nullptr != getInitialValueOfAllocation(CB, TLI, I8Ty)) {
          AllocationInfo *AI = new (A.Allocator) AllocationInfo{CB};
          AllocationInfos[CB] = AI;
          if (TLI)
            TLI->getLibFunc(*CB, AI->LibraryFunctionId);
        }
      }
      return true;
    };

    bool UsedAssumedInformation = false;
    bool Success = A.checkForAllCallLikeInstructions(
        AllocationIdentifierCB, *this, UsedAssumedInformation,
        /* CheckBBLivenessOnly */ false,
        /* CheckPotentiallyDead */ true);
    (void)Success;
    assert(Success && "Did not expect the call base visit callback to fail!");

    Attributor::SimplifictionCallbackTy SCB =
        [](const IRPosition &, const AbstractAttribute *,
           bool &) -> std::optional<Value *> { return nullptr; };
    for (const auto &It : AllocationInfos)
      A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
                                       SCB);
    for (const auto &It : DeallocationInfos)
      A.registerSimplificationCallback(IRPosition::callsite_returned(*It.first),
                                       SCB);
  }

  const std::string getAsStr(Attributor *A) const override {
    unsigned NumH2SMallocs = 0, NumInvalidMallocs = 0;
    for (const auto &It : AllocationInfos) {
      if (It.second->Status == AllocationInfo::INVALID)
        ++NumInvalidMallocs;
      else
        ++NumH2SMallocs;
    }
    return "[H2S] Mallocs Good/Bad: " + std::to_string(NumH2SMallocs) + "/" +
           std::to_string(NumInvalidMallocs);
  }

  /// See AbstractAttribute::trackStatistics().
  void trackStatistics() const override {
    STATS_DECL(
        MallocCalls, Function,
        "Number of malloc/calloc/aligned_alloc calls converted to allocas");
    for (const auto &It : AllocationInfos)
      if (It.second->Status != AllocationInfo::INVALID)
        ++BUILD_STAT_NAME(MallocCalls, Function);
  }

  bool isAssumedHeapToStack(const CallBase &CB) const override {
    if (isValidState())
      if (AllocationInfo *AI =
              AllocationInfos.lookup(const_cast<CallBase *>(&CB)))
        return AI->Status != AllocationInfo::INVALID;
    return false;
  }

  bool isAssumedHeapToStackRemovedFree(CallBase &CB) const override {
    if (!isValidState())
      return false;

    for (const auto &It : AllocationInfos) {
      AllocationInfo &AI = *It.second;
      if (AI.Status == AllocationInfo::INVALID)
        continue;

      if (AI.PotentialFreeCalls.count(&CB))
        return true;
    }

    return false;
  }

  ChangeStatus manifest(Attributor &A) override {
    assert(getState().isValidState() &&
           "Attempted to manifest an invalid state!");

    ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
    Function *F = getAnchorScope();
    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);

    for (auto &It : AllocationInfos) {
      AllocationInfo &AI = *It.second;
      if (AI.Status == AllocationInfo::INVALID)
        continue;

      for (CallBase *FreeCall : AI.PotentialFreeCalls) {
        LLVM_DEBUG(dbgs() << "H2S: Removing free call: " << *FreeCall << "\n");
        A.deleteAfterManifest(*FreeCall);
        HasChanged = ChangeStatus::CHANGED;
      }

      LLVM_DEBUG(dbgs() << "H2S: Removing malloc-like call: " << *AI.CB
                        << "\n");

      auto Remark = [&](OptimizationRemark OR) {
        LibFunc IsAllocShared;
        if (TLI->getLibFunc(*AI.CB, IsAllocShared))
          if (IsAllocShared == LibFunc___kmpc_alloc_shared)
            return OR << "Moving globalized variable to the stack.";
        return OR << "Moving memory allocation from the heap to the stack.";
      };
      if (AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
        A.emitRemark<OptimizationRemark>(AI.CB, "OMP110", Remark);
      else
        A.emitRemark<OptimizationRemark>(AI.CB, "HeapToStack", Remark);

      const DataLayout &DL = A.getInfoCache().getDL();
      Value *Size;
      std::optional<APInt> SizeAPI = getSize(A, *this, AI);
      if (SizeAPI) {
        Size = ConstantInt::get(AI.CB->getContext(), *SizeAPI);
      } else {
        LLVMContext &Ctx = AI.CB->getContext();
        ObjectSizeOpts Opts;
        ObjectSizeOffsetEvaluator Eval(DL, TLI, Ctx, Opts);
        SizeOffsetEvalType SizeOffsetPair = Eval.compute(AI.CB);
        assert(SizeOffsetPair != ObjectSizeOffsetEvaluator::unknown() &&
               cast<ConstantInt>(SizeOffsetPair.second)->isZero());
        Size = SizeOffsetPair.first;
      }

      Instruction *IP =
          AI.MoveAllocaIntoEntry ? &F->getEntryBlock().front() : AI.CB;

      Align Alignment(1);
      if (MaybeAlign RetAlign = AI.CB->getRetAlign())
        Alignment = std::max(Alignment, *RetAlign);
      if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
        std::optional<APInt> AlignmentAPI = getAPInt(A, *this, *Align);
        assert(AlignmentAPI && AlignmentAPI->getZExtValue() > 0 &&
               "Expected an alignment during manifest!");
        Alignment =
            std::max(Alignment, assumeAligned(AlignmentAPI->getZExtValue()));
      }

      // TODO: Hoist the alloca towards the function entry.
      unsigned AS = DL.getAllocaAddrSpace();
      Instruction *Alloca =
          new AllocaInst(Type::getInt8Ty(F->getContext()), AS, Size, Alignment,
                         AI.CB->getName() + ".h2s", IP);

      if (Alloca->getType() != AI.CB->getType())
        Alloca = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
            Alloca, AI.CB->getType(), "malloc_cast", AI.CB);

      auto *I8Ty = Type::getInt8Ty(F->getContext());
      auto *InitVal = getInitialValueOfAllocation(AI.CB, TLI, I8Ty);
      assert(InitVal &&
             "Must be able to materialize initial memory state of allocation");

      A.changeAfterManifest(IRPosition::inst(*AI.CB), *Alloca);

      if (auto *II = dyn_cast<InvokeInst>(AI.CB)) {
        auto *NBB = II->getNormalDest();
        BranchInst::Create(NBB, AI.CB->getParent());
        A.deleteAfterManifest(*AI.CB);
      } else {
        A.deleteAfterManifest(*AI.CB);
      }

      // Initialize the alloca with the same value as used by the allocation
      // function.  We can skip undef as the initial value of an alloc is
      // undef, and the memset would simply end up being DSEd.
      if (!isa<UndefValue>(InitVal)) {
        IRBuilder<> Builder(Alloca->getNextNode());
        // TODO: Use alignment above if align!=1
        Builder.CreateMemSet(Alloca, InitVal, Size, std::nullopt);
      }
      HasChanged = ChangeStatus::CHANGED;
    }

    return HasChanged;
  }

  std::optional<APInt> getAPInt(Attributor &A, const AbstractAttribute &AA,
                                Value &V) {
    bool UsedAssumedInformation = false;
    std::optional<Constant *> SimpleV =
        A.getAssumedConstant(V, AA, UsedAssumedInformation);
    if (!SimpleV)
      return APInt(64, 0);
    if (auto *CI = dyn_cast_or_null<ConstantInt>(*SimpleV))
      return CI->getValue();
    return std::nullopt;
  }

  std::optional<APInt> getSize(Attributor &A, const AbstractAttribute &AA,
                               AllocationInfo &AI) {
    auto Mapper = [&](const Value *V) -> const Value * {
      bool UsedAssumedInformation = false;
      if (std::optional<Constant *> SimpleV =
              A.getAssumedConstant(*V, AA, UsedAssumedInformation))
        if (*SimpleV)
          return *SimpleV;
      return V;
    };

    const Function *F = getAnchorScope();
    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
    return getAllocSize(AI.CB, TLI, Mapper);
  }

  /// Collection of all malloc-like calls in a function with associated
  /// information.
  MapVector<CallBase *, AllocationInfo *> AllocationInfos;

  /// Collection of all free-like calls in a function with associated
  /// information.
  MapVector<CallBase *, DeallocationInfo *> DeallocationInfos;

  ChangeStatus updateImpl(Attributor &A) override;
};

ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {
  ChangeStatus Changed = ChangeStatus::UNCHANGED;
  const Function *F = getAnchorScope();
  const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);

  const auto *LivenessAA =
      A.getAAFor<AAIsDead>(*this, IRPosition::function(*F), DepClassTy::NONE);

  MustBeExecutedContextExplorer *Explorer =
      A.getInfoCache().getMustBeExecutedContextExplorer();

  bool StackIsAccessibleByOtherThreads =
      A.getInfoCache().stackIsAccessibleByOtherThreads();

  LoopInfo *LI =
      A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(*F);
  std::optional<bool> MayContainIrreducibleControl;
  auto IsInLoop = [&](BasicBlock &BB) {
    if (&F->getEntryBlock() == &BB)
      return false;
    if (!MayContainIrreducibleControl.has_value())
      MayContainIrreducibleControl = mayContainIrreducibleControl(*F, LI);
    if (*MayContainIrreducibleControl)
      return true;
    if (!LI)
      return true;
    return LI->getLoopFor(&BB) != nullptr;
  };

  // Flag to ensure we update our deallocation information at most once per
  // updateImpl call and only if we use the free check reasoning.
  bool HasUpdatedFrees = false;

  auto UpdateFrees = [&]() {
    HasUpdatedFrees = true;

    for (auto &It : DeallocationInfos) {
      DeallocationInfo &DI = *It.second;
      // For now we cannot use deallocations that have unknown inputs, skip
      // them.
      if (DI.MightFreeUnknownObjects)
        continue;

      // No need to analyze dead calls, ignore them instead.
      bool UsedAssumedInformation = false;
      if (A.isAssumedDead(*DI.CB, this, LivenessAA, UsedAssumedInformation,
                          /* CheckBBLivenessOnly */ true))
        continue;

      // Use the non-optimistic version to get the freed object.
      Value *Obj = getUnderlyingObject(DI.FreedOp);
      if (!Obj) {
        LLVM_DEBUG(dbgs() << "[H2S] Unknown underlying object for free!\n");
        DI.MightFreeUnknownObjects = true;
        continue;
      }

      // Free of null and undef can be ignored as no-ops (or UB in the latter
      // case).
      if (isa<ConstantPointerNull>(Obj) || isa<UndefValue>(Obj))
        continue;

      CallBase *ObjCB = dyn_cast<CallBase>(Obj);
      if (!ObjCB) {
        LLVM_DEBUG(dbgs() << "[H2S] Free of a non-call object: " << *Obj
                          << "\n");
        DI.MightFreeUnknownObjects = true;
        continue;
      }

      AllocationInfo *AI = AllocationInfos.lookup(ObjCB);
      if (!AI) {
        LLVM_DEBUG(dbgs() << "[H2S] Free of a non-allocation object: " << *Obj
                          << "\n");
        DI.MightFreeUnknownObjects = true;
        continue;
      }

      DI.PotentialAllocationCalls.insert(ObjCB);
    }
  };

  auto FreeCheck = [&](AllocationInfo &AI) {
    // If the stack is not accessible by other threads, the "must-free" logic
    // doesn't apply as the pointer could be shared and needs to be places in
    // "shareable" memory.
    if (!StackIsAccessibleByOtherThreads) {
      bool IsKnownNoSycn;
      if (!AA::hasAssumedIRAttr<Attribute::NoSync>(
              A, this, getIRPosition(), DepClassTy::OPTIONAL, IsKnownNoSycn)) {
        LLVM_DEBUG(
            dbgs() << "[H2S] found an escaping use, stack is not accessible by "
                      "other threads and function is not nosync:\n");
        return false;
      }
    }
    if (!HasUpdatedFrees)
      UpdateFrees();

    // TODO: Allow multi exit functions that have different free calls.
    if (AI.PotentialFreeCalls.size() != 1) {
      LLVM_DEBUG(dbgs() << "[H2S] did not find one free call but "
                        << AI.PotentialFreeCalls.size() << "\n");
      return false;
    }
    CallBase *UniqueFree = *AI.PotentialFreeCalls.begin();
    DeallocationInfo *DI = DeallocationInfos.lookup(UniqueFree);
    if (!DI) {
      LLVM_DEBUG(
          dbgs() << "[H2S] unique free call was not known as deallocation call "
                 << *UniqueFree << "\n");
      return false;
    }
    if (DI->MightFreeUnknownObjects) {
      LLVM_DEBUG(
          dbgs() << "[H2S] unique free call might free unknown allocations\n");
      return false;
    }
    if (DI->PotentialAllocationCalls.empty())
      return true;
    if (DI->PotentialAllocationCalls.size() > 1) {
      LLVM_DEBUG(dbgs() << "[H2S] unique free call might free "
                        << DI->PotentialAllocationCalls.size()
                        << " different allocations\n");
      return false;
    }
    if (*DI->PotentialAllocationCalls.begin() != AI.CB) {
      LLVM_DEBUG(
          dbgs()
          << "[H2S] unique free call not known to free this allocation but "
          << **DI->PotentialAllocationCalls.begin() << "\n");
      return false;
    }
    Instruction *CtxI = isa<InvokeInst>(AI.CB) ? AI.CB : AI.CB->getNextNode();
    if (!Explorer || !Explorer->findInContextOf(UniqueFree, CtxI)) {
      LLVM_DEBUG(
          dbgs()
          << "[H2S] unique free call might not be executed with the allocation "
          << *UniqueFree << "\n");
      return false;
    }
    return true;
  };

  auto UsesCheck = [&](AllocationInfo &AI) {
    bool ValidUsesOnly = true;

    auto Pred = [&](const Use &U, bool &Follow) -> bool {
      Instruction *UserI = cast<Instruction>(U.getUser());
      if (isa<LoadInst>(UserI))
        return true;
      if (auto *SI = dyn_cast<StoreInst>(UserI)) {
        if (SI->getValueOperand() == U.get()) {
          LLVM_DEBUG(dbgs()
                     << "[H2S] escaping store to memory: " << *UserI << "\n");
          ValidUsesOnly = false;
        } else {
          // A store into the malloc'ed memory is fine.
        }
        return true;
      }
      if (auto *CB = dyn_cast<CallBase>(UserI)) {
        if (!CB->isArgOperand(&U) || CB->isLifetimeStartOrEnd())
          return true;
        if (DeallocationInfos.count(CB)) {
          AI.PotentialFreeCalls.insert(CB);
          return true;
        }

        unsigned ArgNo = CB->getArgOperandNo(&U);
        auto CBIRP = IRPosition::callsite_argument(*CB, ArgNo);

        bool IsKnownNoCapture;
        bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
            A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoCapture);

        // If a call site argument use is nofree, we are fine.
        bool IsKnownNoFree;
        bool IsAssumedNoFree = AA::hasAssumedIRAttr<Attribute::NoFree>(
            A, this, CBIRP, DepClassTy::OPTIONAL, IsKnownNoFree);

        if (!IsAssumedNoCapture ||
            (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
             !IsAssumedNoFree)) {
          AI.HasPotentiallyFreeingUnknownUses |= !IsAssumedNoFree;

          // Emit a missed remark if this is missed OpenMP globalization.
          auto Remark = [&](OptimizationRemarkMissed ORM) {
            return ORM
                   << "Could not move globalized variable to the stack. "
                      "Variable is potentially captured in call. Mark "
                      "parameter as `__attribute__((noescape))` to override.";
          };

          if (ValidUsesOnly &&
              AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared)
            A.emitRemark<OptimizationRemarkMissed>(CB, "OMP113", Remark);

          LLVM_DEBUG(dbgs() << "[H2S] Bad user: " << *UserI << "\n");
          ValidUsesOnly = false;
        }
        return true;
      }

      if (isa<GetElementPtrInst>(UserI) || isa<BitCastInst>(UserI) ||
          isa<PHINode>(UserI) || isa<SelectInst>(UserI)) {
        Follow = true;
        return true;
      }
      // Unknown user for which we can not track uses further (in a way that
      // makes sense).
      LLVM_DEBUG(dbgs() << "[H2S] Unknown user: " << *UserI << "\n");
      ValidUsesOnly = false;
      return true;
    };
    if (!A.checkForAllUses(Pred, *this, *AI.CB, /* CheckBBLivenessOnly */ false,
                           DepClassTy::OPTIONAL, /* IgnoreDroppableUses */ true,
                           [&](const Use &OldU, const Use &NewU) {
                             auto *SI = dyn_cast<StoreInst>(OldU.getUser());
                             return !SI || StackIsAccessibleByOtherThreads ||
                                    AA::isAssumedThreadLocalObject(
                                        A, *SI->getPointerOperand(), *this);
                           }))
      return false;
    return ValidUsesOnly;
  };

  // The actual update starts here. We look at all allocations and depending on
  // their status perform the appropriate check(s).
  for (auto &It : AllocationInfos) {
    AllocationInfo &AI = *It.second;
    if (AI.Status == AllocationInfo::INVALID)
      continue;

    if (Value *Align = getAllocAlignment(AI.CB, TLI)) {
      std::optional<APInt> APAlign = getAPInt(A, *this, *Align);
      if (!APAlign) {
        // Can't generate an alloca which respects the required alignment
        // on the allocation.
        LLVM_DEBUG(dbgs() << "[H2S] Unknown allocation alignment: " << *AI.CB
                          << "\n");
        AI.Status = AllocationInfo::INVALID;
        Changed = ChangeStatus::CHANGED;
        continue;
      }
      if (APAlign->ugt(llvm::Value::MaximumAlignment) ||
          !APAlign->isPowerOf2()) {
        LLVM_DEBUG(dbgs() << "[H2S] Invalid allocation alignment: " << APAlign
                          << "\n");
        AI.Status = AllocationInfo::INVALID;
        Changed = ChangeStatus::CHANGED;
        continue;
      }
    }

    std::optional<APInt> Size = getSize(A, *this, AI);
    if (AI.LibraryFunctionId != LibFunc___kmpc_alloc_shared &&
        MaxHeapToStackSize != -1) {
      if (!Size || Size->ugt(MaxHeapToStackSize)) {
        LLVM_DEBUG({
          if (!Size)
            dbgs() << "[H2S] Unknown allocation size: " << *AI.CB << "\n";
          else
            dbgs() << "[H2S] Allocation size too large: " << *AI.CB << " vs. "
                   << MaxHeapToStackSize << "\n";
        });

        AI.Status = AllocationInfo::INVALID;
        Changed = ChangeStatus::CHANGED;
        continue;
      }
    }

    switch (AI.Status) {
    case AllocationInfo::STACK_DUE_TO_USE:
      if (UsesCheck(AI))
        break;
      AI.Status = AllocationInfo::STACK_DUE_TO_FREE;
      [[fallthrough]];
    case AllocationInfo::STACK_DUE_TO_FREE:
      if (FreeCheck(AI))
        break;
      AI.Status = AllocationInfo::INVALID;
      Changed = ChangeStatus::CHANGED;
      break;
    case AllocationInfo::INVALID:
      llvm_unreachable("Invalid allocations should never reach this point!");
    };

    // Check if we still think we can move it into the entry block. If the
    // alloca comes from a converted __kmpc_alloc_shared then we can usually
    // ignore the potential compilations associated with loops.
    bool IsGlobalizedLocal =
        AI.LibraryFunctionId == LibFunc___kmpc_alloc_shared;
    if (AI.MoveAllocaIntoEntry &&
        (!Size.has_value() ||
         (!IsGlobalizedLocal && IsInLoop(*AI.CB->getParent()))))
      AI.MoveAllocaIntoEntry = false;
  }

  return Changed;
}
} // namespace

/// ----------------------- Privatizable Pointers ------------------------------
namespace {
struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {
  AAPrivatizablePtrImpl(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtr(IRP, A), PrivatizableType(std::nullopt) {}

  ChangeStatus indicatePessimisticFixpoint() override {
    AAPrivatizablePtr::indicatePessimisticFixpoint();
    PrivatizableType = nullptr;
    return ChangeStatus::CHANGED;
  }

  /// Identify the type we can chose for a private copy of the underlying
  /// argument. std::nullopt means it is not clear yet, nullptr means there is
  /// none.
  virtual std::optional<Type *> identifyPrivatizableType(Attributor &A) = 0;

  /// Return a privatizable type that encloses both T0 and T1.
  /// TODO: This is merely a stub for now as we should manage a mapping as well.
  std::optional<Type *> combineTypes(std::optional<Type *> T0,
                                     std::optional<Type *> T1) {
    if (!T0)
      return T1;
    if (!T1)
      return T0;
    if (T0 == T1)
      return T0;
    return nullptr;
  }

  std::optional<Type *> getPrivatizableType() const override {
    return PrivatizableType;
  }

  const std::string getAsStr(Attributor *A) const override {
    return isAssumedPrivatizablePtr() ? "[priv]" : "[no-priv]";
  }

protected:
  std::optional<Type *> PrivatizableType;
};

// TODO: Do this for call site arguments (probably also other values) as well.

struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
  AAPrivatizablePtrArgument(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtrImpl(IRP, A) {}

  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
    // If this is a byval argument and we know all the call sites (so we can
    // rewrite them), there is no need to check them explicitly.
    bool UsedAssumedInformation = false;
    SmallVector<Attribute, 1> Attrs;
    A.getAttrs(getIRPosition(), {Attribute::ByVal}, Attrs,
               /* IgnoreSubsumingPositions */ true);
    if (!Attrs.empty() &&
        A.checkForAllCallSites([](AbstractCallSite ACS) { return true; }, *this,
                               true, UsedAssumedInformation))
      return Attrs[0].getValueAsType();

    std::optional<Type *> Ty;
    unsigned ArgNo = getIRPosition().getCallSiteArgNo();

    // Make sure the associated call site argument has the same type at all call
    // sites and it is an allocation we know is safe to privatize, for now that
    // means we only allow alloca instructions.
    // TODO: We can additionally analyze the accesses in the callee to  create
    //       the type from that information instead. That is a little more
    //       involved and will be done in a follow up patch.
    auto CallSiteCheck = [&](AbstractCallSite ACS) {
      IRPosition ACSArgPos = IRPosition::callsite_argument(ACS, ArgNo);
      // Check if a coresponding argument was found or if it is one not
      // associated (which can happen for callback calls).
      if (ACSArgPos.getPositionKind() == IRPosition::IRP_INVALID)
        return false;

      // Check that all call sites agree on a type.
      auto *PrivCSArgAA =
          A.getAAFor<AAPrivatizablePtr>(*this, ACSArgPos, DepClassTy::REQUIRED);
      if (!PrivCSArgAA)
        return false;
      std::optional<Type *> CSTy = PrivCSArgAA->getPrivatizableType();

      LLVM_DEBUG({
        dbgs() << "[AAPrivatizablePtr] ACSPos: " << ACSArgPos << ", CSTy: ";
        if (CSTy && *CSTy)
          (*CSTy)->print(dbgs());
        else if (CSTy)
          dbgs() << "<nullptr>";
        else
          dbgs() << "<none>";
      });

      Ty = combineTypes(Ty, CSTy);

      LLVM_DEBUG({
        dbgs() << " : New Type: ";
        if (Ty && *Ty)
          (*Ty)->print(dbgs());
        else if (Ty)
          dbgs() << "<nullptr>";
        else
          dbgs() << "<none>";
        dbgs() << "\n";
      });

      return !Ty || *Ty;
    };

    if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
                                UsedAssumedInformation))
      return nullptr;
    return Ty;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    PrivatizableType = identifyPrivatizableType(A);
    if (!PrivatizableType)
      return ChangeStatus::UNCHANGED;
    if (!*PrivatizableType)
      return indicatePessimisticFixpoint();

    // The dependence is optional so we don't give up once we give up on the
    // alignment.
    A.getAAFor<AAAlign>(*this, IRPosition::value(getAssociatedValue()),
                        DepClassTy::OPTIONAL);

    // Avoid arguments with padding for now.
    if (!A.hasAttr(getIRPosition(), Attribute::ByVal) &&
        !isDenselyPacked(*PrivatizableType, A.getInfoCache().getDL())) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Padding detected\n");
      return indicatePessimisticFixpoint();
    }

    // Collect the types that will replace the privatizable type in the function
    // signature.
    SmallVector<Type *, 16> ReplacementTypes;
    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);

    // Verify callee and caller agree on how the promoted argument would be
    // passed.
    Function &Fn = *getIRPosition().getAnchorScope();
    const auto *TTI =
        A.getInfoCache().getAnalysisResultForFunction<TargetIRAnalysis>(Fn);
    if (!TTI) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Missing TTI for function "
                        << Fn.getName() << "\n");
      return indicatePessimisticFixpoint();
    }

    auto CallSiteCheck = [&](AbstractCallSite ACS) {
      CallBase *CB = ACS.getInstruction();
      return TTI->areTypesABICompatible(
          CB->getCaller(),
          dyn_cast_if_present<Function>(CB->getCalledOperand()),
          ReplacementTypes);
    };
    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallSites(CallSiteCheck, *this, true,
                                UsedAssumedInformation)) {
      LLVM_DEBUG(
          dbgs() << "[AAPrivatizablePtr] ABI incompatibility detected for "
                 << Fn.getName() << "\n");
      return indicatePessimisticFixpoint();
    }

    // Register a rewrite of the argument.
    Argument *Arg = getAssociatedArgument();
    if (!A.isValidFunctionSignatureRewrite(*Arg, ReplacementTypes)) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Rewrite not valid\n");
      return indicatePessimisticFixpoint();
    }

    unsigned ArgNo = Arg->getArgNo();

    // Helper to check if for the given call site the associated argument is
    // passed to a callback where the privatization would be different.
    auto IsCompatiblePrivArgOfCallback = [&](CallBase &CB) {
      SmallVector<const Use *, 4> CallbackUses;
      AbstractCallSite::getCallbackUses(CB, CallbackUses);
      for (const Use *U : CallbackUses) {
        AbstractCallSite CBACS(U);
        assert(CBACS && CBACS.isCallbackCall());
        for (Argument &CBArg : CBACS.getCalledFunction()->args()) {
          int CBArgNo = CBACS.getCallArgOperandNo(CBArg);

          LLVM_DEBUG({
            dbgs()
                << "[AAPrivatizablePtr] Argument " << *Arg
                << "check if can be privatized in the context of its parent ("
                << Arg->getParent()->getName()
                << ")\n[AAPrivatizablePtr] because it is an argument in a "
                   "callback ("
                << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
                << ")\n[AAPrivatizablePtr] " << CBArg << " : "
                << CBACS.getCallArgOperand(CBArg) << " vs "
                << CB.getArgOperand(ArgNo) << "\n"
                << "[AAPrivatizablePtr] " << CBArg << " : "
                << CBACS.getCallArgOperandNo(CBArg) << " vs " << ArgNo << "\n";
          });

          if (CBArgNo != int(ArgNo))
            continue;
          const auto *CBArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
              *this, IRPosition::argument(CBArg), DepClassTy::REQUIRED);
          if (CBArgPrivAA && CBArgPrivAA->isValidState()) {
            auto CBArgPrivTy = CBArgPrivAA->getPrivatizableType();
            if (!CBArgPrivTy)
              continue;
            if (*CBArgPrivTy == PrivatizableType)
              continue;
          }

          LLVM_DEBUG({
            dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
                   << " cannot be privatized in the context of its parent ("
                   << Arg->getParent()->getName()
                   << ")\n[AAPrivatizablePtr] because it is an argument in a "
                      "callback ("
                   << CBArgNo << "@" << CBACS.getCalledFunction()->getName()
                   << ").\n[AAPrivatizablePtr] for which the argument "
                      "privatization is not compatible.\n";
          });
          return false;
        }
      }
      return true;
    };

    // Helper to check if for the given call site the associated argument is
    // passed to a direct call where the privatization would be different.
    auto IsCompatiblePrivArgOfDirectCS = [&](AbstractCallSite ACS) {
      CallBase *DC = cast<CallBase>(ACS.getInstruction());
      int DCArgNo = ACS.getCallArgOperandNo(ArgNo);
      assert(DCArgNo >= 0 && unsigned(DCArgNo) < DC->arg_size() &&
             "Expected a direct call operand for callback call operand");

      Function *DCCallee =
          dyn_cast_if_present<Function>(DC->getCalledOperand());
      LLVM_DEBUG({
        dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
               << " check if be privatized in the context of its parent ("
               << Arg->getParent()->getName()
               << ")\n[AAPrivatizablePtr] because it is an argument in a "
                  "direct call of ("
               << DCArgNo << "@" << DCCallee->getName() << ").\n";
      });

      if (unsigned(DCArgNo) < DCCallee->arg_size()) {
        const auto *DCArgPrivAA = A.getAAFor<AAPrivatizablePtr>(
            *this, IRPosition::argument(*DCCallee->getArg(DCArgNo)),
            DepClassTy::REQUIRED);
        if (DCArgPrivAA && DCArgPrivAA->isValidState()) {
          auto DCArgPrivTy = DCArgPrivAA->getPrivatizableType();
          if (!DCArgPrivTy)
            return true;
          if (*DCArgPrivTy == PrivatizableType)
            return true;
        }
      }

      LLVM_DEBUG({
        dbgs() << "[AAPrivatizablePtr] Argument " << *Arg
               << " cannot be privatized in the context of its parent ("
               << Arg->getParent()->getName()
               << ")\n[AAPrivatizablePtr] because it is an argument in a "
                  "direct call of ("
               << ACS.getInstruction()->getCalledOperand()->getName()
               << ").\n[AAPrivatizablePtr] for which the argument "
                  "privatization is not compatible.\n";
      });
      return false;
    };

    // Helper to check if the associated argument is used at the given abstract
    // call site in a way that is incompatible with the privatization assumed
    // here.
    auto IsCompatiblePrivArgOfOtherCallSite = [&](AbstractCallSite ACS) {
      if (ACS.isDirectCall())
        return IsCompatiblePrivArgOfCallback(*ACS.getInstruction());
      if (ACS.isCallbackCall())
        return IsCompatiblePrivArgOfDirectCS(ACS);
      return false;
    };

    if (!A.checkForAllCallSites(IsCompatiblePrivArgOfOtherCallSite, *this, true,
                                UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// Given a type to private \p PrivType, collect the constituates (which are
  /// used) in \p ReplacementTypes.
  static void
  identifyReplacementTypes(Type *PrivType,
                           SmallVectorImpl<Type *> &ReplacementTypes) {
    // TODO: For now we expand the privatization type to the fullest which can
    //       lead to dead arguments that need to be removed later.
    assert(PrivType && "Expected privatizable type!");

    // Traverse the type, extract constituate types on the outermost level.
    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++)
        ReplacementTypes.push_back(PrivStructType->getElementType(u));
    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
      ReplacementTypes.append(PrivArrayType->getNumElements(),
                              PrivArrayType->getElementType());
    } else {
      ReplacementTypes.push_back(PrivType);
    }
  }

  /// Initialize \p Base according to the type \p PrivType at position \p IP.
  /// The values needed are taken from the arguments of \p F starting at
  /// position \p ArgNo.
  static void createInitialization(Type *PrivType, Value &Base, Function &F,
                                   unsigned ArgNo, Instruction &IP) {
    assert(PrivType && "Expected privatizable type!");

    IRBuilder<NoFolder> IRB(&IP);
    const DataLayout &DL = F.getParent()->getDataLayout();

    // Traverse the type, build GEPs and stores.
    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
        Type *PointeeTy = PrivStructType->getElementType(u)->getPointerTo();
        Value *Ptr =
            constructPointer(PointeeTy, PrivType, &Base,
                             PrivStructLayout->getElementOffset(u), IRB, DL);
        new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
      }
    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
      Type *PointeeTy = PrivArrayType->getElementType();
      Type *PointeePtrTy = PointeeTy->getPointerTo();
      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
        Value *Ptr = constructPointer(PointeePtrTy, PrivType, &Base,
                                      u * PointeeTySize, IRB, DL);
        new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
      }
    } else {
      new StoreInst(F.getArg(ArgNo), &Base, &IP);
    }
  }

  /// Extract values from \p Base according to the type \p PrivType at the
  /// call position \p ACS. The values are appended to \p ReplacementValues.
  void createReplacementValues(Align Alignment, Type *PrivType,
                               AbstractCallSite ACS, Value *Base,
                               SmallVectorImpl<Value *> &ReplacementValues) {
    assert(Base && "Expected base value!");
    assert(PrivType && "Expected privatizable type!");
    Instruction *IP = ACS.getInstruction();

    IRBuilder<NoFolder> IRB(IP);
    const DataLayout &DL = IP->getModule()->getDataLayout();

    Type *PrivPtrType = PrivType->getPointerTo();
    if (Base->getType() != PrivPtrType)
      Base = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
          Base, PrivPtrType, "", ACS.getInstruction());

    // Traverse the type, build GEPs and loads.
    if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
      const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
      for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
        Type *PointeeTy = PrivStructType->getElementType(u);
        Value *Ptr =
            constructPointer(PointeeTy->getPointerTo(), PrivType, Base,
                             PrivStructLayout->getElementOffset(u), IRB, DL);
        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
        L->setAlignment(Alignment);
        ReplacementValues.push_back(L);
      }
    } else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
      Type *PointeeTy = PrivArrayType->getElementType();
      uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
      Type *PointeePtrTy = PointeeTy->getPointerTo();
      for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
        Value *Ptr = constructPointer(PointeePtrTy, PrivType, Base,
                                      u * PointeeTySize, IRB, DL);
        LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
        L->setAlignment(Alignment);
        ReplacementValues.push_back(L);
      }
    } else {
      LoadInst *L = new LoadInst(PrivType, Base, "", IP);
      L->setAlignment(Alignment);
      ReplacementValues.push_back(L);
    }
  }

  /// See AbstractAttribute::manifest(...)
  ChangeStatus manifest(Attributor &A) override {
    if (!PrivatizableType)
      return ChangeStatus::UNCHANGED;
    assert(*PrivatizableType && "Expected privatizable type!");

    // Collect all tail calls in the function as we cannot allow new allocas to
    // escape into tail recursion.
    // TODO: Be smarter about new allocas escaping into tail calls.
    SmallVector<CallInst *, 16> TailCalls;
    bool UsedAssumedInformation = false;
    if (!A.checkForAllInstructions(
            [&](Instruction &I) {
              CallInst &CI = cast<CallInst>(I);
              if (CI.isTailCall())
                TailCalls.push_back(&CI);
              return true;
            },
            *this, {Instruction::Call}, UsedAssumedInformation))
      return ChangeStatus::UNCHANGED;

    Argument *Arg = getAssociatedArgument();
    // Query AAAlign attribute for alignment of associated argument to
    // determine the best alignment of loads.
    const auto *AlignAA =
        A.getAAFor<AAAlign>(*this, IRPosition::value(*Arg), DepClassTy::NONE);

    // Callback to repair the associated function. A new alloca is placed at the
    // beginning and initialized with the values passed through arguments. The
    // new alloca replaces the use of the old pointer argument.
    Attributor::ArgumentReplacementInfo::CalleeRepairCBTy FnRepairCB =
        [=](const Attributor::ArgumentReplacementInfo &ARI,
            Function &ReplacementFn, Function::arg_iterator ArgIt) {
          BasicBlock &EntryBB = ReplacementFn.getEntryBlock();
          Instruction *IP = &*EntryBB.getFirstInsertionPt();
          const DataLayout &DL = IP->getModule()->getDataLayout();
          unsigned AS = DL.getAllocaAddrSpace();
          Instruction *AI = new AllocaInst(*PrivatizableType, AS,
                                           Arg->getName() + ".priv", IP);
          createInitialization(*PrivatizableType, *AI, ReplacementFn,
                               ArgIt->getArgNo(), *IP);

          if (AI->getType() != Arg->getType())
            AI = BitCastInst::CreatePointerBitCastOrAddrSpaceCast(
                AI, Arg->getType(), "", IP);
          Arg->replaceAllUsesWith(AI);

          for (CallInst *CI : TailCalls)
            CI->setTailCall(false);
        };

    // Callback to repair a call site of the associated function. The elements
    // of the privatizable type are loaded prior to the call and passed to the
    // new function version.
    Attributor::ArgumentReplacementInfo::ACSRepairCBTy ACSRepairCB =
        [=](const Attributor::ArgumentReplacementInfo &ARI,
            AbstractCallSite ACS, SmallVectorImpl<Value *> &NewArgOperands) {
          // When no alignment is specified for the load instruction,
          // natural alignment is assumed.
          createReplacementValues(
              AlignAA ? AlignAA->getAssumedAlign() : Align(0),
              *PrivatizableType, ACS,
              ACS.getCallArgOperand(ARI.getReplacedArg().getArgNo()),
              NewArgOperands);
        };

    // Collect the types that will replace the privatizable type in the function
    // signature.
    SmallVector<Type *, 16> ReplacementTypes;
    identifyReplacementTypes(*PrivatizableType, ReplacementTypes);

    // Register a rewrite of the argument.
    if (A.registerFunctionSignatureRewrite(*Arg, ReplacementTypes,
                                           std::move(FnRepairCB),
                                           std::move(ACSRepairCB)))
      return ChangeStatus::CHANGED;
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(privatizable_ptr);
  }
};

struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {
  AAPrivatizablePtrFloating(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtrImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: We can privatize more than arguments.
    indicatePessimisticFixpoint();
  }

  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("AAPrivatizablePtr(Floating|Returned|CallSiteReturned)::"
                     "updateImpl will not be called");
  }

  /// See AAPrivatizablePtrImpl::identifyPrivatizableType(...)
  std::optional<Type *> identifyPrivatizableType(Attributor &A) override {
    Value *Obj = getUnderlyingObject(&getAssociatedValue());
    if (!Obj) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] No underlying object found!\n");
      return nullptr;
    }

    if (auto *AI = dyn_cast<AllocaInst>(Obj))
      if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
        if (CI->isOne())
          return AI->getAllocatedType();
    if (auto *Arg = dyn_cast<Argument>(Obj)) {
      auto *PrivArgAA = A.getAAFor<AAPrivatizablePtr>(
          *this, IRPosition::argument(*Arg), DepClassTy::REQUIRED);
      if (PrivArgAA && PrivArgAA->isAssumedPrivatizablePtr())
        return PrivArgAA->getPrivatizableType();
    }

    LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] Underlying object neither valid "
                         "alloca nor privatizable argument: "
                      << *Obj << "!\n");
    return nullptr;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(privatizable_ptr);
  }
};

struct AAPrivatizablePtrCallSiteArgument final
    : public AAPrivatizablePtrFloating {
  AAPrivatizablePtrCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtrFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    if (A.hasAttr(getIRPosition(), Attribute::ByVal))
      indicateOptimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    PrivatizableType = identifyPrivatizableType(A);
    if (!PrivatizableType)
      return ChangeStatus::UNCHANGED;
    if (!*PrivatizableType)
      return indicatePessimisticFixpoint();

    const IRPosition &IRP = getIRPosition();
    bool IsKnownNoCapture;
    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
        A, this, IRP, DepClassTy::REQUIRED, IsKnownNoCapture);
    if (!IsAssumedNoCapture) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might be captured!\n");
      return indicatePessimisticFixpoint();
    }

    bool IsKnownNoAlias;
    if (!AA::hasAssumedIRAttr<Attribute::NoAlias>(
            A, this, IRP, DepClassTy::REQUIRED, IsKnownNoAlias)) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer might alias!\n");
      return indicatePessimisticFixpoint();
    }

    bool IsKnown;
    if (!AA::isAssumedReadOnly(A, IRP, *this, IsKnown)) {
      LLVM_DEBUG(dbgs() << "[AAPrivatizablePtr] pointer is written!\n");
      return indicatePessimisticFixpoint();
    }

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(privatizable_ptr);
  }
};

struct AAPrivatizablePtrCallSiteReturned final
    : public AAPrivatizablePtrFloating {
  AAPrivatizablePtrCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtrFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: We can privatize more than arguments.
    indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(privatizable_ptr);
  }
};

struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {
  AAPrivatizablePtrReturned(const IRPosition &IRP, Attributor &A)
      : AAPrivatizablePtrFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: We can privatize more than arguments.
    indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(privatizable_ptr);
  }
};
} // namespace

/// -------------------- Memory Behavior Attributes ----------------------------
/// Includes read-none, read-only, and write-only.
/// ----------------------------------------------------------------------------
namespace {
struct AAMemoryBehaviorImpl : public AAMemoryBehavior {
  AAMemoryBehaviorImpl(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehavior(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    intersectAssumedBits(BEST_STATE);
    getKnownStateFromValue(A, getIRPosition(), getState());
    AAMemoryBehavior::initialize(A);
  }

  /// Return the memory behavior information encoded in the IR for \p IRP.
  static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
                                     BitIntegerState &State,
                                     bool IgnoreSubsumingPositions = false) {
    SmallVector<Attribute, 2> Attrs;
    A.getAttrs(IRP, AttrKinds, Attrs, IgnoreSubsumingPositions);
    for (const Attribute &Attr : Attrs) {
      switch (Attr.getKindAsEnum()) {
      case Attribute::ReadNone:
        State.addKnownBits(NO_ACCESSES);
        break;
      case Attribute::ReadOnly:
        State.addKnownBits(NO_WRITES);
        break;
      case Attribute::WriteOnly:
        State.addKnownBits(NO_READS);
        break;
      default:
        llvm_unreachable("Unexpected attribute!");
      }
    }

    if (auto *I = dyn_cast<Instruction>(&IRP.getAnchorValue())) {
      if (!I->mayReadFromMemory())
        State.addKnownBits(NO_READS);
      if (!I->mayWriteToMemory())
        State.addKnownBits(NO_WRITES);
    }
  }

  /// See AbstractAttribute::getDeducedAttributes(...).
  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    assert(Attrs.size() == 0);
    if (isAssumedReadNone())
      Attrs.push_back(Attribute::get(Ctx, Attribute::ReadNone));
    else if (isAssumedReadOnly())
      Attrs.push_back(Attribute::get(Ctx, Attribute::ReadOnly));
    else if (isAssumedWriteOnly())
      Attrs.push_back(Attribute::get(Ctx, Attribute::WriteOnly));
    assert(Attrs.size() <= 1);
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    const IRPosition &IRP = getIRPosition();

    if (A.hasAttr(IRP, Attribute::ReadNone,
                  /* IgnoreSubsumingPositions */ true))
      return ChangeStatus::UNCHANGED;

    // Check if we would improve the existing attributes first.
    SmallVector<Attribute, 4> DeducedAttrs;
    getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
    if (llvm::all_of(DeducedAttrs, [&](const Attribute &Attr) {
          return A.hasAttr(IRP, Attr.getKindAsEnum(),
                           /* IgnoreSubsumingPositions */ true);
        }))
      return ChangeStatus::UNCHANGED;

    // Clear existing attributes.
    A.removeAttrs(IRP, AttrKinds);

    // Use the generic manifest method.
    return IRAttribute::manifest(A);
  }

  /// See AbstractState::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    if (isAssumedReadNone())
      return "readnone";
    if (isAssumedReadOnly())
      return "readonly";
    if (isAssumedWriteOnly())
      return "writeonly";
    return "may-read/write";
  }

  /// The set of IR attributes AAMemoryBehavior deals with.
  static const Attribute::AttrKind AttrKinds[3];
};

const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] = {
    Attribute::ReadNone, Attribute::ReadOnly, Attribute::WriteOnly};

/// Memory behavior attribute for a floating value.
struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {
  AAMemoryBehaviorFloating(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override;

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_FLOATING_ATTR(readnone)
    else if (isAssumedReadOnly())
      STATS_DECLTRACK_FLOATING_ATTR(readonly)
    else if (isAssumedWriteOnly())
      STATS_DECLTRACK_FLOATING_ATTR(writeonly)
  }

private:
  /// Return true if users of \p UserI might access the underlying
  /// variable/location described by \p U and should therefore be analyzed.
  bool followUsersOfUseIn(Attributor &A, const Use &U,
                          const Instruction *UserI);

  /// Update the state according to the effect of use \p U in \p UserI.
  void analyzeUseIn(Attributor &A, const Use &U, const Instruction *UserI);
};

/// Memory behavior attribute for function argument.
struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {
  AAMemoryBehaviorArgument(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    intersectAssumedBits(BEST_STATE);
    const IRPosition &IRP = getIRPosition();
    // TODO: Make IgnoreSubsumingPositions a property of an IRAttribute so we
    // can query it when we use has/getAttr. That would allow us to reuse the
    // initialize of the base class here.
    bool HasByVal = A.hasAttr(IRP, {Attribute::ByVal},
                              /* IgnoreSubsumingPositions */ true);
    getKnownStateFromValue(A, IRP, getState(),
                           /* IgnoreSubsumingPositions */ HasByVal);
  }

  ChangeStatus manifest(Attributor &A) override {
    // TODO: Pointer arguments are not supported on vectors of pointers yet.
    if (!getAssociatedValue().getType()->isPointerTy())
      return ChangeStatus::UNCHANGED;

    // TODO: From readattrs.ll: "inalloca parameters are always
    //                           considered written"
    if (A.hasAttr(getIRPosition(),
                  {Attribute::InAlloca, Attribute::Preallocated})) {
      removeKnownBits(NO_WRITES);
      removeAssumedBits(NO_WRITES);
    }
    A.removeAttrs(getIRPosition(), AttrKinds);
    return AAMemoryBehaviorFloating::manifest(A);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_ARG_ATTR(readnone)
    else if (isAssumedReadOnly())
      STATS_DECLTRACK_ARG_ATTR(readonly)
    else if (isAssumedWriteOnly())
      STATS_DECLTRACK_ARG_ATTR(writeonly)
  }
};

struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
  AAMemoryBehaviorCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorArgument(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // If we don't have an associated attribute this is either a variadic call
    // or an indirect call, either way, nothing to do here.
    Argument *Arg = getAssociatedArgument();
    if (!Arg) {
      indicatePessimisticFixpoint();
      return;
    }
    if (Arg->hasByValAttr()) {
      addKnownBits(NO_WRITES);
      removeKnownBits(NO_READS);
      removeAssumedBits(NO_READS);
    }
    AAMemoryBehaviorArgument::initialize(A);
    if (getAssociatedFunction()->isDeclaration())
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Argument *Arg = getAssociatedArgument();
    const IRPosition &ArgPos = IRPosition::argument(*Arg);
    auto *ArgAA =
        A.getAAFor<AAMemoryBehavior>(*this, ArgPos, DepClassTy::REQUIRED);
    if (!ArgAA)
      return indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(getState(), ArgAA->getState());
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_CSARG_ATTR(readnone)
    else if (isAssumedReadOnly())
      STATS_DECLTRACK_CSARG_ATTR(readonly)
    else if (isAssumedWriteOnly())
      STATS_DECLTRACK_CSARG_ATTR(writeonly)
  }
};

/// Memory behavior attribute for a call site return position.
struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {
  AAMemoryBehaviorCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAMemoryBehaviorImpl::initialize(A);
  }
  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // We do not annotate returned values.
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}
};

/// An AA to represent the memory behavior function attributes.
struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {
  AAMemoryBehaviorFunction(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(Attributor &A).
  ChangeStatus updateImpl(Attributor &A) override;

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // TODO: It would be better to merge this with AAMemoryLocation, so that
    // we could determine read/write per location. This would also have the
    // benefit of only one place trying to manifest the memory attribute.
    Function &F = cast<Function>(getAnchorValue());
    MemoryEffects ME = MemoryEffects::unknown();
    if (isAssumedReadNone())
      ME = MemoryEffects::none();
    else if (isAssumedReadOnly())
      ME = MemoryEffects::readOnly();
    else if (isAssumedWriteOnly())
      ME = MemoryEffects::writeOnly();

    A.removeAttrs(getIRPosition(), AttrKinds);
    return A.manifestAttrs(getIRPosition(),
                           Attribute::getWithMemoryEffects(F.getContext(), ME));
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_FN_ATTR(readnone)
    else if (isAssumedReadOnly())
      STATS_DECLTRACK_FN_ATTR(readonly)
    else if (isAssumedWriteOnly())
      STATS_DECLTRACK_FN_ATTR(writeonly)
  }
};

/// AAMemoryBehavior attribute for call sites.
struct AAMemoryBehaviorCallSite final : AAMemoryBehaviorImpl {
  AAMemoryBehaviorCallSite(const IRPosition &IRP, Attributor &A)
      : AAMemoryBehaviorImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    auto *FnAA =
        A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::REQUIRED);
    if (!FnAA)
      return indicatePessimisticFixpoint();
    return clampStateAndIndicateChange(getState(), FnAA->getState());
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // TODO: Deduplicate this with AAMemoryBehaviorFunction.
    CallBase &CB = cast<CallBase>(getAnchorValue());
    MemoryEffects ME = MemoryEffects::unknown();
    if (isAssumedReadNone())
      ME = MemoryEffects::none();
    else if (isAssumedReadOnly())
      ME = MemoryEffects::readOnly();
    else if (isAssumedWriteOnly())
      ME = MemoryEffects::writeOnly();

    A.removeAttrs(getIRPosition(), AttrKinds);
    return A.manifestAttrs(
        getIRPosition(), Attribute::getWithMemoryEffects(CB.getContext(), ME));
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_CS_ATTR(readnone)
    else if (isAssumedReadOnly())
      STATS_DECLTRACK_CS_ATTR(readonly)
    else if (isAssumedWriteOnly())
      STATS_DECLTRACK_CS_ATTR(writeonly)
  }
};

ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {

  // The current assumed state used to determine a change.
  auto AssumedState = getAssumed();

  auto CheckRWInst = [&](Instruction &I) {
    // If the instruction has an own memory behavior state, use it to restrict
    // the local state. No further analysis is required as the other memory
    // state is as optimistic as it gets.
    if (const auto *CB = dyn_cast<CallBase>(&I)) {
      const auto *MemBehaviorAA = A.getAAFor<AAMemoryBehavior>(
          *this, IRPosition::callsite_function(*CB), DepClassTy::REQUIRED);
      if (MemBehaviorAA) {
        intersectAssumedBits(MemBehaviorAA->getAssumed());
        return !isAtFixpoint();
      }
    }

    // Remove access kind modifiers if necessary.
    if (I.mayReadFromMemory())
      removeAssumedBits(NO_READS);
    if (I.mayWriteToMemory())
      removeAssumedBits(NO_WRITES);
    return !isAtFixpoint();
  };

  bool UsedAssumedInformation = false;
  if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
                                          UsedAssumedInformation))
    return indicatePessimisticFixpoint();

  return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
                                        : ChangeStatus::UNCHANGED;
}

ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {

  const IRPosition &IRP = getIRPosition();
  const IRPosition &FnPos = IRPosition::function_scope(IRP);
  AAMemoryBehavior::StateType &S = getState();

  // First, check the function scope. We take the known information and we avoid
  // work if the assumed information implies the current assumed information for
  // this attribute. This is a valid for all but byval arguments.
  Argument *Arg = IRP.getAssociatedArgument();
  AAMemoryBehavior::base_t FnMemAssumedState =
      AAMemoryBehavior::StateType::getWorstState();
  if (!Arg || !Arg->hasByValAttr()) {
    const auto *FnMemAA =
        A.getAAFor<AAMemoryBehavior>(*this, FnPos, DepClassTy::OPTIONAL);
    if (FnMemAA) {
      FnMemAssumedState = FnMemAA->getAssumed();
      S.addKnownBits(FnMemAA->getKnown());
      if ((S.getAssumed() & FnMemAA->getAssumed()) == S.getAssumed())
        return ChangeStatus::UNCHANGED;
    }
  }

  // The current assumed state used to determine a change.
  auto AssumedState = S.getAssumed();

  // Make sure the value is not captured (except through "return"), if
  // it is, any information derived would be irrelevant anyway as we cannot
  // check the potential aliases introduced by the capture. However, no need
  // to fall back to anythign less optimistic than the function state.
  bool IsKnownNoCapture;
  const AANoCapture *ArgNoCaptureAA = nullptr;
  bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::NoCapture>(
      A, this, IRP, DepClassTy::OPTIONAL, IsKnownNoCapture, false,
      &ArgNoCaptureAA);

  if (!IsAssumedNoCapture &&
      (!ArgNoCaptureAA || !ArgNoCaptureAA->isAssumedNoCaptureMaybeReturned())) {
    S.intersectAssumedBits(FnMemAssumedState);
    return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
                                          : ChangeStatus::UNCHANGED;
  }

  // Visit and expand uses until all are analyzed or a fixpoint is reached.
  auto UsePred = [&](const Use &U, bool &Follow) -> bool {
    Instruction *UserI = cast<Instruction>(U.getUser());
    LLVM_DEBUG(dbgs() << "[AAMemoryBehavior] Use: " << *U << " in " << *UserI
                      << " \n");

    // Droppable users, e.g., llvm::assume does not actually perform any action.
    if (UserI->isDroppable())
      return true;

    // Check if the users of UserI should also be visited.
    Follow = followUsersOfUseIn(A, U, UserI);

    // If UserI might touch memory we analyze the use in detail.
    if (UserI->mayReadOrWriteMemory())
      analyzeUseIn(A, U, UserI);

    return !isAtFixpoint();
  };

  if (!A.checkForAllUses(UsePred, *this, getAssociatedValue()))
    return indicatePessimisticFixpoint();

  return (AssumedState != getAssumed()) ? ChangeStatus::CHANGED
                                        : ChangeStatus::UNCHANGED;
}

bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
                                                  const Instruction *UserI) {
  // The loaded value is unrelated to the pointer argument, no need to
  // follow the users of the load.
  if (isa<LoadInst>(UserI) || isa<ReturnInst>(UserI))
    return false;

  // By default we follow all uses assuming UserI might leak information on U,
  // we have special handling for call sites operands though.
  const auto *CB = dyn_cast<CallBase>(UserI);
  if (!CB || !CB->isArgOperand(&U))
    return true;

  // If the use is a call argument known not to be captured, the users of
  // the call do not need to be visited because they have to be unrelated to
  // the input. Note that this check is not trivial even though we disallow
  // general capturing of the underlying argument. The reason is that the
  // call might the argument "through return", which we allow and for which we
  // need to check call users.
  if (U.get()->getType()->isPointerTy()) {
    unsigned ArgNo = CB->getArgOperandNo(&U);
    bool IsKnownNoCapture;
    return !AA::hasAssumedIRAttr<Attribute::NoCapture>(
        A, this, IRPosition::callsite_argument(*CB, ArgNo),
        DepClassTy::OPTIONAL, IsKnownNoCapture);
  }

  return true;
}

void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
                                            const Instruction *UserI) {
  assert(UserI->mayReadOrWriteMemory());

  switch (UserI->getOpcode()) {
  default:
    // TODO: Handle all atomics and other side-effect operations we know of.
    break;
  case Instruction::Load:
    // Loads cause the NO_READS property to disappear.
    removeAssumedBits(NO_READS);
    return;

  case Instruction::Store:
    // Stores cause the NO_WRITES property to disappear if the use is the
    // pointer operand. Note that while capturing was taken care of somewhere
    // else we need to deal with stores of the value that is not looked through.
    if (cast<StoreInst>(UserI)->getPointerOperand() == U.get())
      removeAssumedBits(NO_WRITES);
    else
      indicatePessimisticFixpoint();
    return;

  case Instruction::Call:
  case Instruction::CallBr:
  case Instruction::Invoke: {
    // For call sites we look at the argument memory behavior attribute (this
    // could be recursive!) in order to restrict our own state.
    const auto *CB = cast<CallBase>(UserI);

    // Give up on operand bundles.
    if (CB->isBundleOperand(&U)) {
      indicatePessimisticFixpoint();
      return;
    }

    // Calling a function does read the function pointer, maybe write it if the
    // function is self-modifying.
    if (CB->isCallee(&U)) {
      removeAssumedBits(NO_READS);
      break;
    }

    // Adjust the possible access behavior based on the information on the
    // argument.
    IRPosition Pos;
    if (U.get()->getType()->isPointerTy())
      Pos = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
    else
      Pos = IRPosition::callsite_function(*CB);
    const auto *MemBehaviorAA =
        A.getAAFor<AAMemoryBehavior>(*this, Pos, DepClassTy::OPTIONAL);
    if (!MemBehaviorAA)
      break;
    // "assumed" has at most the same bits as the MemBehaviorAA assumed
    // and at least "known".
    intersectAssumedBits(MemBehaviorAA->getAssumed());
    return;
  }
  };

  // Generally, look at the "may-properties" and adjust the assumed state if we
  // did not trigger special handling before.
  if (UserI->mayReadFromMemory())
    removeAssumedBits(NO_READS);
  if (UserI->mayWriteToMemory())
    removeAssumedBits(NO_WRITES);
}
} // namespace

/// -------------------- Memory Locations Attributes ---------------------------
/// Includes read-none, argmemonly, inaccessiblememonly,
/// inaccessiblememorargmemonly
/// ----------------------------------------------------------------------------

std::string AAMemoryLocation::getMemoryLocationsAsStr(
    AAMemoryLocation::MemoryLocationsKind MLK) {
  if (0 == (MLK & AAMemoryLocation::NO_LOCATIONS))
    return "all memory";
  if (MLK == AAMemoryLocation::NO_LOCATIONS)
    return "no memory";
  std::string S = "memory:";
  if (0 == (MLK & AAMemoryLocation::NO_LOCAL_MEM))
    S += "stack,";
  if (0 == (MLK & AAMemoryLocation::NO_CONST_MEM))
    S += "constant,";
  if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_INTERNAL_MEM))
    S += "internal global,";
  if (0 == (MLK & AAMemoryLocation::NO_GLOBAL_EXTERNAL_MEM))
    S += "external global,";
  if (0 == (MLK & AAMemoryLocation::NO_ARGUMENT_MEM))
    S += "argument,";
  if (0 == (MLK & AAMemoryLocation::NO_INACCESSIBLE_MEM))
    S += "inaccessible,";
  if (0 == (MLK & AAMemoryLocation::NO_MALLOCED_MEM))
    S += "malloced,";
  if (0 == (MLK & AAMemoryLocation::NO_UNKOWN_MEM))
    S += "unknown,";
  S.pop_back();
  return S;
}

namespace {
struct AAMemoryLocationImpl : public AAMemoryLocation {

  AAMemoryLocationImpl(const IRPosition &IRP, Attributor &A)
      : AAMemoryLocation(IRP, A), Allocator(A.Allocator) {
    AccessKind2Accesses.fill(nullptr);
  }

  ~AAMemoryLocationImpl() {
    // The AccessSets are allocated via a BumpPtrAllocator, we call
    // the destructor manually.
    for (AccessSet *AS : AccessKind2Accesses)
      if (AS)
        AS->~AccessSet();
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    intersectAssumedBits(BEST_STATE);
    getKnownStateFromValue(A, getIRPosition(), getState());
    AAMemoryLocation::initialize(A);
  }

  /// Return the memory behavior information encoded in the IR for \p IRP.
  static void getKnownStateFromValue(Attributor &A, const IRPosition &IRP,
                                     BitIntegerState &State,
                                     bool IgnoreSubsumingPositions = false) {
    // For internal functions we ignore `argmemonly` and
    // `inaccessiblememorargmemonly` as we might break it via interprocedural
    // constant propagation. It is unclear if this is the best way but it is
    // unlikely this will cause real performance problems. If we are deriving
    // attributes for the anchor function we even remove the attribute in
    // addition to ignoring it.
    // TODO: A better way to handle this would be to add ~NO_GLOBAL_MEM /
    // MemoryEffects::Other as a possible location.
    bool UseArgMemOnly = true;
    Function *AnchorFn = IRP.getAnchorScope();
    if (AnchorFn && A.isRunOn(*AnchorFn))
      UseArgMemOnly = !AnchorFn->hasLocalLinkage();

    SmallVector<Attribute, 2> Attrs;
    A.getAttrs(IRP, {Attribute::Memory}, Attrs, IgnoreSubsumingPositions);
    for (const Attribute &Attr : Attrs) {
      // TODO: We can map MemoryEffects to Attributor locations more precisely.
      MemoryEffects ME = Attr.getMemoryEffects();
      if (ME.doesNotAccessMemory()) {
        State.addKnownBits(NO_LOCAL_MEM | NO_CONST_MEM);
        continue;
      }
      if (ME.onlyAccessesInaccessibleMem()) {
        State.addKnownBits(inverseLocation(NO_INACCESSIBLE_MEM, true, true));
        continue;
      }
      if (ME.onlyAccessesArgPointees()) {
        if (UseArgMemOnly)
          State.addKnownBits(inverseLocation(NO_ARGUMENT_MEM, true, true));
        else {
          // Remove location information, only keep read/write info.
          ME = MemoryEffects(ME.getModRef());
          A.manifestAttrs(IRP,
                          Attribute::getWithMemoryEffects(
                              IRP.getAnchorValue().getContext(), ME),
                          /*ForceReplace*/ true);
        }
        continue;
      }
      if (ME.onlyAccessesInaccessibleOrArgMem()) {
        if (UseArgMemOnly)
          State.addKnownBits(inverseLocation(
              NO_INACCESSIBLE_MEM | NO_ARGUMENT_MEM, true, true));
        else {
          // Remove location information, only keep read/write info.
          ME = MemoryEffects(ME.getModRef());
          A.manifestAttrs(IRP,
                          Attribute::getWithMemoryEffects(
                              IRP.getAnchorValue().getContext(), ME),
                          /*ForceReplace*/ true);
        }
        continue;
      }
    }
  }

  /// See AbstractAttribute::getDeducedAttributes(...).
  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    // TODO: We can map Attributor locations to MemoryEffects more precisely.
    assert(Attrs.size() == 0);
    if (getIRPosition().getPositionKind() == IRPosition::IRP_FUNCTION) {
      if (isAssumedReadNone())
        Attrs.push_back(
            Attribute::getWithMemoryEffects(Ctx, MemoryEffects::none()));
      else if (isAssumedInaccessibleMemOnly())
        Attrs.push_back(Attribute::getWithMemoryEffects(
            Ctx, MemoryEffects::inaccessibleMemOnly()));
      else if (isAssumedArgMemOnly())
        Attrs.push_back(
            Attribute::getWithMemoryEffects(Ctx, MemoryEffects::argMemOnly()));
      else if (isAssumedInaccessibleOrArgMemOnly())
        Attrs.push_back(Attribute::getWithMemoryEffects(
            Ctx, MemoryEffects::inaccessibleOrArgMemOnly()));
    }
    assert(Attrs.size() <= 1);
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // TODO: If AAMemoryLocation and AAMemoryBehavior are merged, we could
    // provide per-location modref information here.
    const IRPosition &IRP = getIRPosition();

    SmallVector<Attribute, 1> DeducedAttrs;
    getDeducedAttributes(A, IRP.getAnchorValue().getContext(), DeducedAttrs);
    if (DeducedAttrs.size() != 1)
      return ChangeStatus::UNCHANGED;
    MemoryEffects ME = DeducedAttrs[0].getMemoryEffects();

    return A.manifestAttrs(IRP, Attribute::getWithMemoryEffects(
                                    IRP.getAnchorValue().getContext(), ME));
  }

  /// See AAMemoryLocation::checkForAllAccessesToMemoryKind(...).
  bool checkForAllAccessesToMemoryKind(
      function_ref<bool(const Instruction *, const Value *, AccessKind,
                        MemoryLocationsKind)>
          Pred,
      MemoryLocationsKind RequestedMLK) const override {
    if (!isValidState())
      return false;

    MemoryLocationsKind AssumedMLK = getAssumedNotAccessedLocation();
    if (AssumedMLK == NO_LOCATIONS)
      return true;

    unsigned Idx = 0;
    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS;
         CurMLK *= 2, ++Idx) {
      if (CurMLK & RequestedMLK)
        continue;

      if (const AccessSet *Accesses = AccessKind2Accesses[Idx])
        for (const AccessInfo &AI : *Accesses)
          if (!Pred(AI.I, AI.Ptr, AI.Kind, CurMLK))
            return false;
    }

    return true;
  }

  ChangeStatus indicatePessimisticFixpoint() override {
    // If we give up and indicate a pessimistic fixpoint this instruction will
    // become an access for all potential access kinds:
    // TODO: Add pointers for argmemonly and globals to improve the results of
    //       checkForAllAccessesToMemoryKind.
    bool Changed = false;
    MemoryLocationsKind KnownMLK = getKnown();
    Instruction *I = dyn_cast<Instruction>(&getAssociatedValue());
    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2)
      if (!(CurMLK & KnownMLK))
        updateStateAndAccessesMap(getState(), CurMLK, I, nullptr, Changed,
                                  getAccessKindFromInst(I));
    return AAMemoryLocation::indicatePessimisticFixpoint();
  }

protected:
  /// Helper struct to tie together an instruction that has a read or write
  /// effect with the pointer it accesses (if any).
  struct AccessInfo {

    /// The instruction that caused the access.
    const Instruction *I;

    /// The base pointer that is accessed, or null if unknown.
    const Value *Ptr;

    /// The kind of access (read/write/read+write).
    AccessKind Kind;

    bool operator==(const AccessInfo &RHS) const {
      return I == RHS.I && Ptr == RHS.Ptr && Kind == RHS.Kind;
    }
    bool operator()(const AccessInfo &LHS, const AccessInfo &RHS) const {
      if (LHS.I != RHS.I)
        return LHS.I < RHS.I;
      if (LHS.Ptr != RHS.Ptr)
        return LHS.Ptr < RHS.Ptr;
      if (LHS.Kind != RHS.Kind)
        return LHS.Kind < RHS.Kind;
      return false;
    }
  };

  /// Mapping from *single* memory location kinds, e.g., LOCAL_MEM with the
  /// value of NO_LOCAL_MEM, to the accesses encountered for this memory kind.
  using AccessSet = SmallSet<AccessInfo, 2, AccessInfo>;
  std::array<AccessSet *, llvm::CTLog2<VALID_STATE>()> AccessKind2Accesses;

  /// Categorize the pointer arguments of CB that might access memory in
  /// AccessedLoc and update the state and access map accordingly.
  void
  categorizeArgumentPointerLocations(Attributor &A, CallBase &CB,
                                     AAMemoryLocation::StateType &AccessedLocs,
                                     bool &Changed);

  /// Return the kind(s) of location that may be accessed by \p V.
  AAMemoryLocation::MemoryLocationsKind
  categorizeAccessedLocations(Attributor &A, Instruction &I, bool &Changed);

  /// Return the access kind as determined by \p I.
  AccessKind getAccessKindFromInst(const Instruction *I) {
    AccessKind AK = READ_WRITE;
    if (I) {
      AK = I->mayReadFromMemory() ? READ : NONE;
      AK = AccessKind(AK | (I->mayWriteToMemory() ? WRITE : NONE));
    }
    return AK;
  }

  /// Update the state \p State and the AccessKind2Accesses given that \p I is
  /// an access of kind \p AK to a \p MLK memory location with the access
  /// pointer \p Ptr.
  void updateStateAndAccessesMap(AAMemoryLocation::StateType &State,
                                 MemoryLocationsKind MLK, const Instruction *I,
                                 const Value *Ptr, bool &Changed,
                                 AccessKind AK = READ_WRITE) {

    assert(isPowerOf2_32(MLK) && "Expected a single location set!");
    auto *&Accesses = AccessKind2Accesses[llvm::Log2_32(MLK)];
    if (!Accesses)
      Accesses = new (Allocator) AccessSet();
    Changed |= Accesses->insert(AccessInfo{I, Ptr, AK}).second;
    if (MLK == NO_UNKOWN_MEM)
      MLK = NO_LOCATIONS;
    State.removeAssumedBits(MLK);
  }

  /// Determine the underlying locations kinds for \p Ptr, e.g., globals or
  /// arguments, and update the state and access map accordingly.
  void categorizePtrValue(Attributor &A, const Instruction &I, const Value &Ptr,
                          AAMemoryLocation::StateType &State, bool &Changed,
                          unsigned AccessAS = 0);

  /// Used to allocate access sets.
  BumpPtrAllocator &Allocator;
};

void AAMemoryLocationImpl::categorizePtrValue(
    Attributor &A, const Instruction &I, const Value &Ptr,
    AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {
  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize pointer locations for "
                    << Ptr << " ["
                    << getMemoryLocationsAsStr(State.getAssumed()) << "]\n");

  auto Pred = [&](Value &Obj) {
    unsigned ObjectAS = Obj.getType()->getPointerAddressSpace();
    // TODO: recognize the TBAA used for constant accesses.
    MemoryLocationsKind MLK = NO_LOCATIONS;

    // Filter accesses to constant (GPU) memory if we have an AS at the access
    // site or the object is known to actually have the associated AS.
    if ((AccessAS == (unsigned)AA::GPUAddressSpace::Constant ||
         (ObjectAS == (unsigned)AA::GPUAddressSpace::Constant &&
          isIdentifiedObject(&Obj))) &&
        AA::isGPU(*I.getModule()))
      return true;

    if (isa<UndefValue>(&Obj))
      return true;
    if (isa<Argument>(&Obj)) {
      // TODO: For now we do not treat byval arguments as local copies performed
      // on the call edge, though, we should. To make that happen we need to
      // teach various passes, e.g., DSE, about the copy effect of a byval. That
      // would also allow us to mark functions only accessing byval arguments as
      // readnone again, arguably their accesses have no effect outside of the
      // function, like accesses to allocas.
      MLK = NO_ARGUMENT_MEM;
    } else if (auto *GV = dyn_cast<GlobalValue>(&Obj)) {
      // Reading constant memory is not treated as a read "effect" by the
      // function attr pass so we won't neither. Constants defined by TBAA are
      // similar. (We know we do not write it because it is constant.)
      if (auto *GVar = dyn_cast<GlobalVariable>(GV))
        if (GVar->isConstant())
          return true;

      if (GV->hasLocalLinkage())
        MLK = NO_GLOBAL_INTERNAL_MEM;
      else
        MLK = NO_GLOBAL_EXTERNAL_MEM;
    } else if (isa<ConstantPointerNull>(&Obj) &&
               (!NullPointerIsDefined(getAssociatedFunction(), AccessAS) ||
                !NullPointerIsDefined(getAssociatedFunction(), ObjectAS))) {
      return true;
    } else if (isa<AllocaInst>(&Obj)) {
      MLK = NO_LOCAL_MEM;
    } else if (const auto *CB = dyn_cast<CallBase>(&Obj)) {
      bool IsKnownNoAlias;
      if (AA::hasAssumedIRAttr<Attribute::NoAlias>(
              A, this, IRPosition::callsite_returned(*CB), DepClassTy::OPTIONAL,
              IsKnownNoAlias))
        MLK = NO_MALLOCED_MEM;
      else
        MLK = NO_UNKOWN_MEM;
    } else {
      MLK = NO_UNKOWN_MEM;
    }

    assert(MLK != NO_LOCATIONS && "No location specified!");
    LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Ptr value can be categorized: "
                      << Obj << " -> " << getMemoryLocationsAsStr(MLK) << "\n");
    updateStateAndAccessesMap(State, MLK, &I, &Obj, Changed,
                              getAccessKindFromInst(&I));

    return true;
  };

  const auto *AA = A.getAAFor<AAUnderlyingObjects>(
      *this, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
  if (!AA || !AA->forallUnderlyingObjects(Pred, AA::Intraprocedural)) {
    LLVM_DEBUG(
        dbgs() << "[AAMemoryLocation] Pointer locations not categorized\n");
    updateStateAndAccessesMap(State, NO_UNKOWN_MEM, &I, nullptr, Changed,
                              getAccessKindFromInst(&I));
    return;
  }

  LLVM_DEBUG(
      dbgs() << "[AAMemoryLocation] Accessed locations with pointer locations: "
             << getMemoryLocationsAsStr(State.getAssumed()) << "\n");
}

void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
    Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
    bool &Changed) {
  for (unsigned ArgNo = 0, E = CB.arg_size(); ArgNo < E; ++ArgNo) {

    // Skip non-pointer arguments.
    const Value *ArgOp = CB.getArgOperand(ArgNo);
    if (!ArgOp->getType()->isPtrOrPtrVectorTy())
      continue;

    // Skip readnone arguments.
    const IRPosition &ArgOpIRP = IRPosition::callsite_argument(CB, ArgNo);
    const auto *ArgOpMemLocationAA =
        A.getAAFor<AAMemoryBehavior>(*this, ArgOpIRP, DepClassTy::OPTIONAL);

    if (ArgOpMemLocationAA && ArgOpMemLocationAA->isAssumedReadNone())
      continue;

    // Categorize potentially accessed pointer arguments as if there was an
    // access instruction with them as pointer.
    categorizePtrValue(A, CB, *ArgOp, AccessedLocs, Changed);
  }
}

AAMemoryLocation::MemoryLocationsKind
AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
                                                  bool &Changed) {
  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize accessed locations for "
                    << I << "\n");

  AAMemoryLocation::StateType AccessedLocs;
  AccessedLocs.intersectAssumedBits(NO_LOCATIONS);

  if (auto *CB = dyn_cast<CallBase>(&I)) {

    // First check if we assume any memory is access is visible.
    const auto *CBMemLocationAA = A.getAAFor<AAMemoryLocation>(
        *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
    LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Categorize call site: " << I
                      << " [" << CBMemLocationAA << "]\n");
    if (!CBMemLocationAA) {
      updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr,
                                Changed, getAccessKindFromInst(&I));
      return NO_UNKOWN_MEM;
    }

    if (CBMemLocationAA->isAssumedReadNone())
      return NO_LOCATIONS;

    if (CBMemLocationAA->isAssumedInaccessibleMemOnly()) {
      updateStateAndAccessesMap(AccessedLocs, NO_INACCESSIBLE_MEM, &I, nullptr,
                                Changed, getAccessKindFromInst(&I));
      return AccessedLocs.getAssumed();
    }

    uint32_t CBAssumedNotAccessedLocs =
        CBMemLocationAA->getAssumedNotAccessedLocation();

    // Set the argmemonly and global bit as we handle them separately below.
    uint32_t CBAssumedNotAccessedLocsNoArgMem =
        CBAssumedNotAccessedLocs | NO_ARGUMENT_MEM | NO_GLOBAL_MEM;

    for (MemoryLocationsKind CurMLK = 1; CurMLK < NO_LOCATIONS; CurMLK *= 2) {
      if (CBAssumedNotAccessedLocsNoArgMem & CurMLK)
        continue;
      updateStateAndAccessesMap(AccessedLocs, CurMLK, &I, nullptr, Changed,
                                getAccessKindFromInst(&I));
    }

    // Now handle global memory if it might be accessed. This is slightly tricky
    // as NO_GLOBAL_MEM has multiple bits set.
    bool HasGlobalAccesses = ((~CBAssumedNotAccessedLocs) & NO_GLOBAL_MEM);
    if (HasGlobalAccesses) {
      auto AccessPred = [&](const Instruction *, const Value *Ptr,
                            AccessKind Kind, MemoryLocationsKind MLK) {
        updateStateAndAccessesMap(AccessedLocs, MLK, &I, Ptr, Changed,
                                  getAccessKindFromInst(&I));
        return true;
      };
      if (!CBMemLocationAA->checkForAllAccessesToMemoryKind(
              AccessPred, inverseLocation(NO_GLOBAL_MEM, false, false)))
        return AccessedLocs.getWorstState();
    }

    LLVM_DEBUG(
        dbgs() << "[AAMemoryLocation] Accessed state before argument handling: "
               << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");

    // Now handle argument memory if it might be accessed.
    bool HasArgAccesses = ((~CBAssumedNotAccessedLocs) & NO_ARGUMENT_MEM);
    if (HasArgAccesses)
      categorizeArgumentPointerLocations(A, *CB, AccessedLocs, Changed);

    LLVM_DEBUG(
        dbgs() << "[AAMemoryLocation] Accessed state after argument handling: "
               << getMemoryLocationsAsStr(AccessedLocs.getAssumed()) << "\n");

    return AccessedLocs.getAssumed();
  }

  if (const Value *Ptr = getPointerOperand(&I, /* AllowVolatile */ true)) {
    LLVM_DEBUG(
        dbgs() << "[AAMemoryLocation] Categorize memory access with pointer: "
               << I << " [" << *Ptr << "]\n");
    categorizePtrValue(A, I, *Ptr, AccessedLocs, Changed,
                       Ptr->getType()->getPointerAddressSpace());
    return AccessedLocs.getAssumed();
  }

  LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Failed to categorize instruction: "
                    << I << "\n");
  updateStateAndAccessesMap(AccessedLocs, NO_UNKOWN_MEM, &I, nullptr, Changed,
                            getAccessKindFromInst(&I));
  return AccessedLocs.getAssumed();
}

/// An AA to represent the memory behavior function attributes.
struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {
  AAMemoryLocationFunction(const IRPosition &IRP, Attributor &A)
      : AAMemoryLocationImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(Attributor &A).
  ChangeStatus updateImpl(Attributor &A) override {

    const auto *MemBehaviorAA =
        A.getAAFor<AAMemoryBehavior>(*this, getIRPosition(), DepClassTy::NONE);
    if (MemBehaviorAA && MemBehaviorAA->isAssumedReadNone()) {
      if (MemBehaviorAA->isKnownReadNone())
        return indicateOptimisticFixpoint();
      assert(isAssumedReadNone() &&
             "AAMemoryLocation was not read-none but AAMemoryBehavior was!");
      A.recordDependence(*MemBehaviorAA, *this, DepClassTy::OPTIONAL);
      return ChangeStatus::UNCHANGED;
    }

    // The current assumed state used to determine a change.
    auto AssumedState = getAssumed();
    bool Changed = false;

    auto CheckRWInst = [&](Instruction &I) {
      MemoryLocationsKind MLK = categorizeAccessedLocations(A, I, Changed);
      LLVM_DEBUG(dbgs() << "[AAMemoryLocation] Accessed locations for " << I
                        << ": " << getMemoryLocationsAsStr(MLK) << "\n");
      removeAssumedBits(inverseLocation(MLK, false, false));
      // Stop once only the valid bit set in the *not assumed location*, thus
      // once we don't actually exclude any memory locations in the state.
      return getAssumedNotAccessedLocation() != VALID_STATE;
    };

    bool UsedAssumedInformation = false;
    if (!A.checkForAllReadWriteInstructions(CheckRWInst, *this,
                                            UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    Changed |= AssumedState != getAssumed();
    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_FN_ATTR(readnone)
    else if (isAssumedArgMemOnly())
      STATS_DECLTRACK_FN_ATTR(argmemonly)
    else if (isAssumedInaccessibleMemOnly())
      STATS_DECLTRACK_FN_ATTR(inaccessiblememonly)
    else if (isAssumedInaccessibleOrArgMemOnly())
      STATS_DECLTRACK_FN_ATTR(inaccessiblememorargmemonly)
  }
};

/// AAMemoryLocation attribute for call sites.
struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {
  AAMemoryLocationCallSite(const IRPosition &IRP, Attributor &A)
      : AAMemoryLocationImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    // TODO: Once we have call site specific value information we can provide
    //       call site specific liveness liveness information and then it makes
    //       sense to specialize attributes for call sites arguments instead of
    //       redirecting requests to the callee argument.
    Function *F = getAssociatedFunction();
    const IRPosition &FnPos = IRPosition::function(*F);
    auto *FnAA =
        A.getAAFor<AAMemoryLocation>(*this, FnPos, DepClassTy::REQUIRED);
    if (!FnAA)
      return indicatePessimisticFixpoint();
    bool Changed = false;
    auto AccessPred = [&](const Instruction *I, const Value *Ptr,
                          AccessKind Kind, MemoryLocationsKind MLK) {
      updateStateAndAccessesMap(getState(), MLK, I, Ptr, Changed,
                                getAccessKindFromInst(I));
      return true;
    };
    if (!FnAA->checkForAllAccessesToMemoryKind(AccessPred, ALL_LOCATIONS))
      return indicatePessimisticFixpoint();
    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    if (isAssumedReadNone())
      STATS_DECLTRACK_CS_ATTR(readnone)
  }
};
} // namespace

/// ------------------ Value Constant Range Attribute -------------------------

namespace {
struct AAValueConstantRangeImpl : AAValueConstantRange {
  using StateType = IntegerRangeState;
  AAValueConstantRangeImpl(const IRPosition &IRP, Attributor &A)
      : AAValueConstantRange(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    if (A.hasSimplificationCallback(getIRPosition())) {
      indicatePessimisticFixpoint();
      return;
    }

    // Intersect a range given by SCEV.
    intersectKnown(getConstantRangeFromSCEV(A, getCtxI()));

    // Intersect a range given by LVI.
    intersectKnown(getConstantRangeFromLVI(A, getCtxI()));
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    std::string Str;
    llvm::raw_string_ostream OS(Str);
    OS << "range(" << getBitWidth() << ")<";
    getKnown().print(OS);
    OS << " / ";
    getAssumed().print(OS);
    OS << ">";
    return OS.str();
  }

  /// Helper function to get a SCEV expr for the associated value at program
  /// point \p I.
  const SCEV *getSCEV(Attributor &A, const Instruction *I = nullptr) const {
    if (!getAnchorScope())
      return nullptr;

    ScalarEvolution *SE =
        A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
            *getAnchorScope());

    LoopInfo *LI = A.getInfoCache().getAnalysisResultForFunction<LoopAnalysis>(
        *getAnchorScope());

    if (!SE || !LI)
      return nullptr;

    const SCEV *S = SE->getSCEV(&getAssociatedValue());
    if (!I)
      return S;

    return SE->getSCEVAtScope(S, LI->getLoopFor(I->getParent()));
  }

  /// Helper function to get a range from SCEV for the associated value at
  /// program point \p I.
  ConstantRange getConstantRangeFromSCEV(Attributor &A,
                                         const Instruction *I = nullptr) const {
    if (!getAnchorScope())
      return getWorstState(getBitWidth());

    ScalarEvolution *SE =
        A.getInfoCache().getAnalysisResultForFunction<ScalarEvolutionAnalysis>(
            *getAnchorScope());

    const SCEV *S = getSCEV(A, I);
    if (!SE || !S)
      return getWorstState(getBitWidth());

    return SE->getUnsignedRange(S);
  }

  /// Helper function to get a range from LVI for the associated value at
  /// program point \p I.
  ConstantRange
  getConstantRangeFromLVI(Attributor &A,
                          const Instruction *CtxI = nullptr) const {
    if (!getAnchorScope())
      return getWorstState(getBitWidth());

    LazyValueInfo *LVI =
        A.getInfoCache().getAnalysisResultForFunction<LazyValueAnalysis>(
            *getAnchorScope());

    if (!LVI || !CtxI)
      return getWorstState(getBitWidth());
    return LVI->getConstantRange(&getAssociatedValue(),
                                 const_cast<Instruction *>(CtxI));
  }

  /// Return true if \p CtxI is valid for querying outside analyses.
  /// This basically makes sure we do not ask intra-procedural analysis
  /// about a context in the wrong function or a context that violates
  /// dominance assumptions they might have. The \p AllowAACtxI flag indicates
  /// if the original context of this AA is OK or should be considered invalid.
  bool isValidCtxInstructionForOutsideAnalysis(Attributor &A,
                                               const Instruction *CtxI,
                                               bool AllowAACtxI) const {
    if (!CtxI || (!AllowAACtxI && CtxI == getCtxI()))
      return false;

    // Our context might be in a different function, neither intra-procedural
    // analysis (ScalarEvolution nor LazyValueInfo) can handle that.
    if (!AA::isValidInScope(getAssociatedValue(), CtxI->getFunction()))
      return false;

    // If the context is not dominated by the value there are paths to the
    // context that do not define the value. This cannot be handled by
    // LazyValueInfo so we need to bail.
    if (auto *I = dyn_cast<Instruction>(&getAssociatedValue())) {
      InformationCache &InfoCache = A.getInfoCache();
      const DominatorTree *DT =
          InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
              *I->getFunction());
      return DT && DT->dominates(I, CtxI);
    }

    return true;
  }

  /// See AAValueConstantRange::getKnownConstantRange(..).
  ConstantRange
  getKnownConstantRange(Attributor &A,
                        const Instruction *CtxI = nullptr) const override {
    if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
                                                 /* AllowAACtxI */ false))
      return getKnown();

    ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
    ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
    return getKnown().intersectWith(SCEVR).intersectWith(LVIR);
  }

  /// See AAValueConstantRange::getAssumedConstantRange(..).
  ConstantRange
  getAssumedConstantRange(Attributor &A,
                          const Instruction *CtxI = nullptr) const override {
    // TODO: Make SCEV use Attributor assumption.
    //       We may be able to bound a variable range via assumptions in
    //       Attributor. ex.) If x is assumed to be in [1, 3] and y is known to
    //       evolve to x^2 + x, then we can say that y is in [2, 12].
    if (!isValidCtxInstructionForOutsideAnalysis(A, CtxI,
                                                 /* AllowAACtxI */ false))
      return getAssumed();

    ConstantRange LVIR = getConstantRangeFromLVI(A, CtxI);
    ConstantRange SCEVR = getConstantRangeFromSCEV(A, CtxI);
    return getAssumed().intersectWith(SCEVR).intersectWith(LVIR);
  }

  /// Helper function to create MDNode for range metadata.
  static MDNode *
  getMDNodeForConstantRange(Type *Ty, LLVMContext &Ctx,
                            const ConstantRange &AssumedConstantRange) {
    Metadata *LowAndHigh[] = {ConstantAsMetadata::get(ConstantInt::get(
                                  Ty, AssumedConstantRange.getLower())),
                              ConstantAsMetadata::get(ConstantInt::get(
                                  Ty, AssumedConstantRange.getUpper()))};
    return MDNode::get(Ctx, LowAndHigh);
  }

  /// Return true if \p Assumed is included in \p KnownRanges.
  static bool isBetterRange(const ConstantRange &Assumed, MDNode *KnownRanges) {

    if (Assumed.isFullSet())
      return false;

    if (!KnownRanges)
      return true;

    // If multiple ranges are annotated in IR, we give up to annotate assumed
    // range for now.

    // TODO:  If there exists a known range which containts assumed range, we
    // can say assumed range is better.
    if (KnownRanges->getNumOperands() > 2)
      return false;

    ConstantInt *Lower =
        mdconst::extract<ConstantInt>(KnownRanges->getOperand(0));
    ConstantInt *Upper =
        mdconst::extract<ConstantInt>(KnownRanges->getOperand(1));

    ConstantRange Known(Lower->getValue(), Upper->getValue());
    return Known.contains(Assumed) && Known != Assumed;
  }

  /// Helper function to set range metadata.
  static bool
  setRangeMetadataIfisBetterRange(Instruction *I,
                                  const ConstantRange &AssumedConstantRange) {
    auto *OldRangeMD = I->getMetadata(LLVMContext::MD_range);
    if (isBetterRange(AssumedConstantRange, OldRangeMD)) {
      if (!AssumedConstantRange.isEmptySet()) {
        I->setMetadata(LLVMContext::MD_range,
                       getMDNodeForConstantRange(I->getType(), I->getContext(),
                                                 AssumedConstantRange));
        return true;
      }
    }
    return false;
  }

  /// See AbstractAttribute::manifest()
  ChangeStatus manifest(Attributor &A) override {
    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    ConstantRange AssumedConstantRange = getAssumedConstantRange(A);
    assert(!AssumedConstantRange.isFullSet() && "Invalid state");

    auto &V = getAssociatedValue();
    if (!AssumedConstantRange.isEmptySet() &&
        !AssumedConstantRange.isSingleElement()) {
      if (Instruction *I = dyn_cast<Instruction>(&V)) {
        assert(I == getCtxI() && "Should not annotate an instruction which is "
                                 "not the context instruction");
        if (isa<CallInst>(I) || isa<LoadInst>(I))
          if (setRangeMetadataIfisBetterRange(I, AssumedConstantRange))
            Changed = ChangeStatus::CHANGED;
      }
    }

    return Changed;
  }
};

struct AAValueConstantRangeArgument final
    : AAArgumentFromCallSiteArguments<
          AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
          true /* BridgeCallBaseContext */> {
  using Base = AAArgumentFromCallSiteArguments<
      AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
      true /* BridgeCallBaseContext */>;
  AAValueConstantRangeArgument(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(value_range)
  }
};

struct AAValueConstantRangeReturned
    : AAReturnedFromReturnedValues<AAValueConstantRange,
                                   AAValueConstantRangeImpl,
                                   AAValueConstantRangeImpl::StateType,
                                   /* PropogateCallBaseContext */ true> {
  using Base =
      AAReturnedFromReturnedValues<AAValueConstantRange,
                                   AAValueConstantRangeImpl,
                                   AAValueConstantRangeImpl::StateType,
                                   /* PropogateCallBaseContext */ true>;
  AAValueConstantRangeReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(value_range)
  }
};

struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {
  AAValueConstantRangeFloating(const IRPosition &IRP, Attributor &A)
      : AAValueConstantRangeImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AAValueConstantRangeImpl::initialize(A);
    if (isAtFixpoint())
      return;

    Value &V = getAssociatedValue();

    if (auto *C = dyn_cast<ConstantInt>(&V)) {
      unionAssumed(ConstantRange(C->getValue()));
      indicateOptimisticFixpoint();
      return;
    }

    if (isa<UndefValue>(&V)) {
      // Collapse the undef state to 0.
      unionAssumed(ConstantRange(APInt(getBitWidth(), 0)));
      indicateOptimisticFixpoint();
      return;
    }

    if (isa<CallBase>(&V))
      return;

    if (isa<BinaryOperator>(&V) || isa<CmpInst>(&V) || isa<CastInst>(&V))
      return;

    // If it is a load instruction with range metadata, use it.
    if (LoadInst *LI = dyn_cast<LoadInst>(&V))
      if (auto *RangeMD = LI->getMetadata(LLVMContext::MD_range)) {
        intersectKnown(getConstantRangeFromMetadata(*RangeMD));
        return;
      }

    // We can work with PHI and select instruction as we traverse their operands
    // during update.
    if (isa<SelectInst>(V) || isa<PHINode>(V))
      return;

    // Otherwise we give up.
    indicatePessimisticFixpoint();

    LLVM_DEBUG(dbgs() << "[AAValueConstantRange] We give up: "
                      << getAssociatedValue() << "\n");
  }

  bool calculateBinaryOperator(
      Attributor &A, BinaryOperator *BinOp, IntegerRangeState &T,
      const Instruction *CtxI,
      SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
    Value *LHS = BinOp->getOperand(0);
    Value *RHS = BinOp->getOperand(1);

    // Simplify the operands first.
    bool UsedAssumedInformation = false;
    const auto &SimplifiedLHS = A.getAssumedSimplified(
        IRPosition::value(*LHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Interprocedural);
    if (!SimplifiedLHS.has_value())
      return true;
    if (!*SimplifiedLHS)
      return false;
    LHS = *SimplifiedLHS;

    const auto &SimplifiedRHS = A.getAssumedSimplified(
        IRPosition::value(*RHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Interprocedural);
    if (!SimplifiedRHS.has_value())
      return true;
    if (!*SimplifiedRHS)
      return false;
    RHS = *SimplifiedRHS;

    // TODO: Allow non integers as well.
    if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
      return false;

    auto *LHSAA = A.getAAFor<AAValueConstantRange>(
        *this, IRPosition::value(*LHS, getCallBaseContext()),
        DepClassTy::REQUIRED);
    if (!LHSAA)
      return false;
    QuerriedAAs.push_back(LHSAA);
    auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);

    auto *RHSAA = A.getAAFor<AAValueConstantRange>(
        *this, IRPosition::value(*RHS, getCallBaseContext()),
        DepClassTy::REQUIRED);
    if (!RHSAA)
      return false;
    QuerriedAAs.push_back(RHSAA);
    auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);

    auto AssumedRange = LHSAARange.binaryOp(BinOp->getOpcode(), RHSAARange);

    T.unionAssumed(AssumedRange);

    // TODO: Track a known state too.

    return T.isValidState();
  }

  bool calculateCastInst(
      Attributor &A, CastInst *CastI, IntegerRangeState &T,
      const Instruction *CtxI,
      SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
    assert(CastI->getNumOperands() == 1 && "Expected cast to be unary!");
    // TODO: Allow non integers as well.
    Value *OpV = CastI->getOperand(0);

    // Simplify the operand first.
    bool UsedAssumedInformation = false;
    const auto &SimplifiedOpV = A.getAssumedSimplified(
        IRPosition::value(*OpV, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Interprocedural);
    if (!SimplifiedOpV.has_value())
      return true;
    if (!*SimplifiedOpV)
      return false;
    OpV = *SimplifiedOpV;

    if (!OpV->getType()->isIntegerTy())
      return false;

    auto *OpAA = A.getAAFor<AAValueConstantRange>(
        *this, IRPosition::value(*OpV, getCallBaseContext()),
        DepClassTy::REQUIRED);
    if (!OpAA)
      return false;
    QuerriedAAs.push_back(OpAA);
    T.unionAssumed(OpAA->getAssumed().castOp(CastI->getOpcode(),
                                             getState().getBitWidth()));
    return T.isValidState();
  }

  bool
  calculateCmpInst(Attributor &A, CmpInst *CmpI, IntegerRangeState &T,
                   const Instruction *CtxI,
                   SmallVectorImpl<const AAValueConstantRange *> &QuerriedAAs) {
    Value *LHS = CmpI->getOperand(0);
    Value *RHS = CmpI->getOperand(1);

    // Simplify the operands first.
    bool UsedAssumedInformation = false;
    const auto &SimplifiedLHS = A.getAssumedSimplified(
        IRPosition::value(*LHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Interprocedural);
    if (!SimplifiedLHS.has_value())
      return true;
    if (!*SimplifiedLHS)
      return false;
    LHS = *SimplifiedLHS;

    const auto &SimplifiedRHS = A.getAssumedSimplified(
        IRPosition::value(*RHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Interprocedural);
    if (!SimplifiedRHS.has_value())
      return true;
    if (!*SimplifiedRHS)
      return false;
    RHS = *SimplifiedRHS;

    // TODO: Allow non integers as well.
    if (!LHS->getType()->isIntegerTy() || !RHS->getType()->isIntegerTy())
      return false;

    auto *LHSAA = A.getAAFor<AAValueConstantRange>(
        *this, IRPosition::value(*LHS, getCallBaseContext()),
        DepClassTy::REQUIRED);
    if (!LHSAA)
      return false;
    QuerriedAAs.push_back(LHSAA);
    auto *RHSAA = A.getAAFor<AAValueConstantRange>(
        *this, IRPosition::value(*RHS, getCallBaseContext()),
        DepClassTy::REQUIRED);
    if (!RHSAA)
      return false;
    QuerriedAAs.push_back(RHSAA);
    auto LHSAARange = LHSAA->getAssumedConstantRange(A, CtxI);
    auto RHSAARange = RHSAA->getAssumedConstantRange(A, CtxI);

    // If one of them is empty set, we can't decide.
    if (LHSAARange.isEmptySet() || RHSAARange.isEmptySet())
      return true;

    bool MustTrue = false, MustFalse = false;

    auto AllowedRegion =
        ConstantRange::makeAllowedICmpRegion(CmpI->getPredicate(), RHSAARange);

    if (AllowedRegion.intersectWith(LHSAARange).isEmptySet())
      MustFalse = true;

    if (LHSAARange.icmp(CmpI->getPredicate(), RHSAARange))
      MustTrue = true;

    assert((!MustTrue || !MustFalse) &&
           "Either MustTrue or MustFalse should be false!");

    if (MustTrue)
      T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 1)));
    else if (MustFalse)
      T.unionAssumed(ConstantRange(APInt(/* numBits */ 1, /* val */ 0)));
    else
      T.unionAssumed(ConstantRange(/* BitWidth */ 1, /* isFullSet */ true));

    LLVM_DEBUG(dbgs() << "[AAValueConstantRange] " << *CmpI << " after "
                      << (MustTrue ? "true" : (MustFalse ? "false" : "unknown"))
                      << ": " << T << "\n\t" << *LHSAA << "\t<op>\n\t"
                      << *RHSAA);

    // TODO: Track a known state too.
    return T.isValidState();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {

    IntegerRangeState T(getBitWidth());
    auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
      Instruction *I = dyn_cast<Instruction>(&V);
      if (!I || isa<CallBase>(I)) {

        // Simplify the operand first.
        bool UsedAssumedInformation = false;
        const auto &SimplifiedOpV = A.getAssumedSimplified(
            IRPosition::value(V, getCallBaseContext()), *this,
            UsedAssumedInformation, AA::Interprocedural);
        if (!SimplifiedOpV.has_value())
          return true;
        if (!*SimplifiedOpV)
          return false;
        Value *VPtr = *SimplifiedOpV;

        // If the value is not instruction, we query AA to Attributor.
        const auto *AA = A.getAAFor<AAValueConstantRange>(
            *this, IRPosition::value(*VPtr, getCallBaseContext()),
            DepClassTy::REQUIRED);

        // Clamp operator is not used to utilize a program point CtxI.
        if (AA)
          T.unionAssumed(AA->getAssumedConstantRange(A, CtxI));
        else
          return false;

        return T.isValidState();
      }

      SmallVector<const AAValueConstantRange *, 4> QuerriedAAs;
      if (auto *BinOp = dyn_cast<BinaryOperator>(I)) {
        if (!calculateBinaryOperator(A, BinOp, T, CtxI, QuerriedAAs))
          return false;
      } else if (auto *CmpI = dyn_cast<CmpInst>(I)) {
        if (!calculateCmpInst(A, CmpI, T, CtxI, QuerriedAAs))
          return false;
      } else if (auto *CastI = dyn_cast<CastInst>(I)) {
        if (!calculateCastInst(A, CastI, T, CtxI, QuerriedAAs))
          return false;
      } else {
        // Give up with other instructions.
        // TODO: Add other instructions

        T.indicatePessimisticFixpoint();
        return false;
      }

      // Catch circular reasoning in a pessimistic way for now.
      // TODO: Check how the range evolves and if we stripped anything, see also
      //       AADereferenceable or AAAlign for similar situations.
      for (const AAValueConstantRange *QueriedAA : QuerriedAAs) {
        if (QueriedAA != this)
          continue;
        // If we are in a stady state we do not need to worry.
        if (T.getAssumed() == getState().getAssumed())
          continue;
        T.indicatePessimisticFixpoint();
      }

      return T.isValidState();
    };

    if (!VisitValueCB(getAssociatedValue(), getCtxI()))
      return indicatePessimisticFixpoint();

    // Ensure that long def-use chains can't cause circular reasoning either by
    // introducing a cutoff below.
    if (clampStateAndIndicateChange(getState(), T) == ChangeStatus::UNCHANGED)
      return ChangeStatus::UNCHANGED;
    if (++NumChanges > MaxNumChanges) {
      LLVM_DEBUG(dbgs() << "[AAValueConstantRange] performed " << NumChanges
                        << " but only " << MaxNumChanges
                        << " are allowed to avoid cyclic reasoning.");
      return indicatePessimisticFixpoint();
    }
    return ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(value_range)
  }

  /// Tracker to bail after too many widening steps of the constant range.
  int NumChanges = 0;

  /// Upper bound for the number of allowed changes (=widening steps) for the
  /// constant range before we give up.
  static constexpr int MaxNumChanges = 5;
};

struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {
  AAValueConstantRangeFunction(const IRPosition &IRP, Attributor &A)
      : AAValueConstantRangeImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("AAValueConstantRange(Function|CallSite)::updateImpl will "
                     "not be called");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FN_ATTR(value_range) }
};

struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {
  AAValueConstantRangeCallSite(const IRPosition &IRP, Attributor &A)
      : AAValueConstantRangeFunction(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CS_ATTR(value_range) }
};

struct AAValueConstantRangeCallSiteReturned
    : AACallSiteReturnedFromReturned<AAValueConstantRange,
                                     AAValueConstantRangeImpl,
                                     AAValueConstantRangeImpl::StateType,
                                     /* IntroduceCallBaseContext */ true> {
  AAValueConstantRangeCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AACallSiteReturnedFromReturned<AAValueConstantRange,
                                       AAValueConstantRangeImpl,
                                       AAValueConstantRangeImpl::StateType,
                                       /* IntroduceCallBaseContext */ true>(IRP,
                                                                            A) {
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // If it is a load instruction with range metadata, use the metadata.
    if (CallInst *CI = dyn_cast<CallInst>(&getAssociatedValue()))
      if (auto *RangeMD = CI->getMetadata(LLVMContext::MD_range))
        intersectKnown(getConstantRangeFromMetadata(*RangeMD));

    AAValueConstantRangeImpl::initialize(A);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(value_range)
  }
};
struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {
  AAValueConstantRangeCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAValueConstantRangeFloating(IRP, A) {}

  /// See AbstractAttribute::manifest()
  ChangeStatus manifest(Attributor &A) override {
    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(value_range)
  }
};
} // namespace

/// ------------------ Potential Values Attribute -------------------------

namespace {
struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {
  using StateType = PotentialConstantIntValuesState;

  AAPotentialConstantValuesImpl(const IRPosition &IRP, Attributor &A)
      : AAPotentialConstantValues(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    if (A.hasSimplificationCallback(getIRPosition()))
      indicatePessimisticFixpoint();
    else
      AAPotentialConstantValues::initialize(A);
  }

  bool fillSetWithConstantValues(Attributor &A, const IRPosition &IRP, SetTy &S,
                                 bool &ContainsUndef, bool ForSelf) {
    SmallVector<AA::ValueAndContext> Values;
    bool UsedAssumedInformation = false;
    if (!A.getAssumedSimplifiedValues(IRP, *this, Values, AA::Interprocedural,
                                      UsedAssumedInformation)) {
      // Avoid recursion when the caller is computing constant values for this
      // IRP itself.
      if (ForSelf)
        return false;
      if (!IRP.getAssociatedType()->isIntegerTy())
        return false;
      auto *PotentialValuesAA = A.getAAFor<AAPotentialConstantValues>(
          *this, IRP, DepClassTy::REQUIRED);
      if (!PotentialValuesAA || !PotentialValuesAA->getState().isValidState())
        return false;
      ContainsUndef = PotentialValuesAA->getState().undefIsContained();
      S = PotentialValuesAA->getState().getAssumedSet();
      return true;
    }

    // Copy all the constant values, except UndefValue. ContainsUndef is true
    // iff Values contains only UndefValue instances. If there are other known
    // constants, then UndefValue is dropped.
    ContainsUndef = false;
    for (auto &It : Values) {
      if (isa<UndefValue>(It.getValue())) {
        ContainsUndef = true;
        continue;
      }
      auto *CI = dyn_cast<ConstantInt>(It.getValue());
      if (!CI)
        return false;
      S.insert(CI->getValue());
    }
    ContainsUndef &= S.empty();

    return true;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    std::string Str;
    llvm::raw_string_ostream OS(Str);
    OS << getState();
    return OS.str();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    return indicatePessimisticFixpoint();
  }
};

struct AAPotentialConstantValuesArgument final
    : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
                                      AAPotentialConstantValuesImpl,
                                      PotentialConstantIntValuesState> {
  using Base = AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
                                               AAPotentialConstantValuesImpl,
                                               PotentialConstantIntValuesState>;
  AAPotentialConstantValuesArgument(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesReturned
    : AAReturnedFromReturnedValues<AAPotentialConstantValues,
                                   AAPotentialConstantValuesImpl> {
  using Base = AAReturnedFromReturnedValues<AAPotentialConstantValues,
                                            AAPotentialConstantValuesImpl>;
  AAPotentialConstantValuesReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  void initialize(Attributor &A) override {
    if (!A.isFunctionIPOAmendable(*getAssociatedFunction()))
      indicatePessimisticFixpoint();
    Base::initialize(A);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {
  AAPotentialConstantValuesFloating(const IRPosition &IRP, Attributor &A)
      : AAPotentialConstantValuesImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    AAPotentialConstantValuesImpl::initialize(A);
    if (isAtFixpoint())
      return;

    Value &V = getAssociatedValue();

    if (auto *C = dyn_cast<ConstantInt>(&V)) {
      unionAssumed(C->getValue());
      indicateOptimisticFixpoint();
      return;
    }

    if (isa<UndefValue>(&V)) {
      unionAssumedWithUndef();
      indicateOptimisticFixpoint();
      return;
    }

    if (isa<BinaryOperator>(&V) || isa<ICmpInst>(&V) || isa<CastInst>(&V))
      return;

    if (isa<SelectInst>(V) || isa<PHINode>(V) || isa<LoadInst>(V))
      return;

    indicatePessimisticFixpoint();

    LLVM_DEBUG(dbgs() << "[AAPotentialConstantValues] We give up: "
                      << getAssociatedValue() << "\n");
  }

  static bool calculateICmpInst(const ICmpInst *ICI, const APInt &LHS,
                                const APInt &RHS) {
    return ICmpInst::compare(LHS, RHS, ICI->getPredicate());
  }

  static APInt calculateCastInst(const CastInst *CI, const APInt &Src,
                                 uint32_t ResultBitWidth) {
    Instruction::CastOps CastOp = CI->getOpcode();
    switch (CastOp) {
    default:
      llvm_unreachable("unsupported or not integer cast");
    case Instruction::Trunc:
      return Src.trunc(ResultBitWidth);
    case Instruction::SExt:
      return Src.sext(ResultBitWidth);
    case Instruction::ZExt:
      return Src.zext(ResultBitWidth);
    case Instruction::BitCast:
      return Src;
    }
  }

  static APInt calculateBinaryOperator(const BinaryOperator *BinOp,
                                       const APInt &LHS, const APInt &RHS,
                                       bool &SkipOperation, bool &Unsupported) {
    Instruction::BinaryOps BinOpcode = BinOp->getOpcode();
    // Unsupported is set to true when the binary operator is not supported.
    // SkipOperation is set to true when UB occur with the given operand pair
    // (LHS, RHS).
    // TODO: we should look at nsw and nuw keywords to handle operations
    //       that create poison or undef value.
    switch (BinOpcode) {
    default:
      Unsupported = true;
      return LHS;
    case Instruction::Add:
      return LHS + RHS;
    case Instruction::Sub:
      return LHS - RHS;
    case Instruction::Mul:
      return LHS * RHS;
    case Instruction::UDiv:
      if (RHS.isZero()) {
        SkipOperation = true;
        return LHS;
      }
      return LHS.udiv(RHS);
    case Instruction::SDiv:
      if (RHS.isZero()) {
        SkipOperation = true;
        return LHS;
      }
      return LHS.sdiv(RHS);
    case Instruction::URem:
      if (RHS.isZero()) {
        SkipOperation = true;
        return LHS;
      }
      return LHS.urem(RHS);
    case Instruction::SRem:
      if (RHS.isZero()) {
        SkipOperation = true;
        return LHS;
      }
      return LHS.srem(RHS);
    case Instruction::Shl:
      return LHS.shl(RHS);
    case Instruction::LShr:
      return LHS.lshr(RHS);
    case Instruction::AShr:
      return LHS.ashr(RHS);
    case Instruction::And:
      return LHS & RHS;
    case Instruction::Or:
      return LHS | RHS;
    case Instruction::Xor:
      return LHS ^ RHS;
    }
  }

  bool calculateBinaryOperatorAndTakeUnion(const BinaryOperator *BinOp,
                                           const APInt &LHS, const APInt &RHS) {
    bool SkipOperation = false;
    bool Unsupported = false;
    APInt Result =
        calculateBinaryOperator(BinOp, LHS, RHS, SkipOperation, Unsupported);
    if (Unsupported)
      return false;
    // If SkipOperation is true, we can ignore this operand pair (L, R).
    if (!SkipOperation)
      unionAssumed(Result);
    return isValidState();
  }

  ChangeStatus updateWithICmpInst(Attributor &A, ICmpInst *ICI) {
    auto AssumedBefore = getAssumed();
    Value *LHS = ICI->getOperand(0);
    Value *RHS = ICI->getOperand(1);

    bool LHSContainsUndef = false, RHSContainsUndef = false;
    SetTy LHSAAPVS, RHSAAPVS;
    if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
                                   LHSContainsUndef, /* ForSelf */ false) ||
        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
                                   RHSContainsUndef, /* ForSelf */ false))
      return indicatePessimisticFixpoint();

    // TODO: make use of undef flag to limit potential values aggressively.
    bool MaybeTrue = false, MaybeFalse = false;
    const APInt Zero(RHS->getType()->getIntegerBitWidth(), 0);
    if (LHSContainsUndef && RHSContainsUndef) {
      // The result of any comparison between undefs can be soundly replaced
      // with undef.
      unionAssumedWithUndef();
    } else if (LHSContainsUndef) {
      for (const APInt &R : RHSAAPVS) {
        bool CmpResult = calculateICmpInst(ICI, Zero, R);
        MaybeTrue |= CmpResult;
        MaybeFalse |= !CmpResult;
        if (MaybeTrue & MaybeFalse)
          return indicatePessimisticFixpoint();
      }
    } else if (RHSContainsUndef) {
      for (const APInt &L : LHSAAPVS) {
        bool CmpResult = calculateICmpInst(ICI, L, Zero);
        MaybeTrue |= CmpResult;
        MaybeFalse |= !CmpResult;
        if (MaybeTrue & MaybeFalse)
          return indicatePessimisticFixpoint();
      }
    } else {
      for (const APInt &L : LHSAAPVS) {
        for (const APInt &R : RHSAAPVS) {
          bool CmpResult = calculateICmpInst(ICI, L, R);
          MaybeTrue |= CmpResult;
          MaybeFalse |= !CmpResult;
          if (MaybeTrue & MaybeFalse)
            return indicatePessimisticFixpoint();
        }
      }
    }
    if (MaybeTrue)
      unionAssumed(APInt(/* numBits */ 1, /* val */ 1));
    if (MaybeFalse)
      unionAssumed(APInt(/* numBits */ 1, /* val */ 0));
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  ChangeStatus updateWithSelectInst(Attributor &A, SelectInst *SI) {
    auto AssumedBefore = getAssumed();
    Value *LHS = SI->getTrueValue();
    Value *RHS = SI->getFalseValue();

    bool UsedAssumedInformation = false;
    std::optional<Constant *> C = A.getAssumedConstant(
        *SI->getCondition(), *this, UsedAssumedInformation);

    // Check if we only need one operand.
    bool OnlyLeft = false, OnlyRight = false;
    if (C && *C && (*C)->isOneValue())
      OnlyLeft = true;
    else if (C && *C && (*C)->isZeroValue())
      OnlyRight = true;

    bool LHSContainsUndef = false, RHSContainsUndef = false;
    SetTy LHSAAPVS, RHSAAPVS;
    if (!OnlyRight &&
        !fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
                                   LHSContainsUndef, /* ForSelf */ false))
      return indicatePessimisticFixpoint();

    if (!OnlyLeft &&
        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
                                   RHSContainsUndef, /* ForSelf */ false))
      return indicatePessimisticFixpoint();

    if (OnlyLeft || OnlyRight) {
      // select (true/false), lhs, rhs
      auto *OpAA = OnlyLeft ? &LHSAAPVS : &RHSAAPVS;
      auto Undef = OnlyLeft ? LHSContainsUndef : RHSContainsUndef;

      if (Undef)
        unionAssumedWithUndef();
      else {
        for (const auto &It : *OpAA)
          unionAssumed(It);
      }

    } else if (LHSContainsUndef && RHSContainsUndef) {
      // select i1 *, undef , undef => undef
      unionAssumedWithUndef();
    } else {
      for (const auto &It : LHSAAPVS)
        unionAssumed(It);
      for (const auto &It : RHSAAPVS)
        unionAssumed(It);
    }
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  ChangeStatus updateWithCastInst(Attributor &A, CastInst *CI) {
    auto AssumedBefore = getAssumed();
    if (!CI->isIntegerCast())
      return indicatePessimisticFixpoint();
    assert(CI->getNumOperands() == 1 && "Expected cast to be unary!");
    uint32_t ResultBitWidth = CI->getDestTy()->getIntegerBitWidth();
    Value *Src = CI->getOperand(0);

    bool SrcContainsUndef = false;
    SetTy SrcPVS;
    if (!fillSetWithConstantValues(A, IRPosition::value(*Src), SrcPVS,
                                   SrcContainsUndef, /* ForSelf */ false))
      return indicatePessimisticFixpoint();

    if (SrcContainsUndef)
      unionAssumedWithUndef();
    else {
      for (const APInt &S : SrcPVS) {
        APInt T = calculateCastInst(CI, S, ResultBitWidth);
        unionAssumed(T);
      }
    }
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  ChangeStatus updateWithBinaryOperator(Attributor &A, BinaryOperator *BinOp) {
    auto AssumedBefore = getAssumed();
    Value *LHS = BinOp->getOperand(0);
    Value *RHS = BinOp->getOperand(1);

    bool LHSContainsUndef = false, RHSContainsUndef = false;
    SetTy LHSAAPVS, RHSAAPVS;
    if (!fillSetWithConstantValues(A, IRPosition::value(*LHS), LHSAAPVS,
                                   LHSContainsUndef, /* ForSelf */ false) ||
        !fillSetWithConstantValues(A, IRPosition::value(*RHS), RHSAAPVS,
                                   RHSContainsUndef, /* ForSelf */ false))
      return indicatePessimisticFixpoint();

    const APInt Zero = APInt(LHS->getType()->getIntegerBitWidth(), 0);

    // TODO: make use of undef flag to limit potential values aggressively.
    if (LHSContainsUndef && RHSContainsUndef) {
      if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, Zero))
        return indicatePessimisticFixpoint();
    } else if (LHSContainsUndef) {
      for (const APInt &R : RHSAAPVS) {
        if (!calculateBinaryOperatorAndTakeUnion(BinOp, Zero, R))
          return indicatePessimisticFixpoint();
      }
    } else if (RHSContainsUndef) {
      for (const APInt &L : LHSAAPVS) {
        if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, Zero))
          return indicatePessimisticFixpoint();
      }
    } else {
      for (const APInt &L : LHSAAPVS) {
        for (const APInt &R : RHSAAPVS) {
          if (!calculateBinaryOperatorAndTakeUnion(BinOp, L, R))
            return indicatePessimisticFixpoint();
        }
      }
    }
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  ChangeStatus updateWithInstruction(Attributor &A, Instruction *Inst) {
    auto AssumedBefore = getAssumed();
    SetTy Incoming;
    bool ContainsUndef;
    if (!fillSetWithConstantValues(A, IRPosition::value(*Inst), Incoming,
                                   ContainsUndef, /* ForSelf */ true))
      return indicatePessimisticFixpoint();
    if (ContainsUndef) {
      unionAssumedWithUndef();
    } else {
      for (const auto &It : Incoming)
        unionAssumed(It);
    }
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    Value &V = getAssociatedValue();
    Instruction *I = dyn_cast<Instruction>(&V);

    if (auto *ICI = dyn_cast<ICmpInst>(I))
      return updateWithICmpInst(A, ICI);

    if (auto *SI = dyn_cast<SelectInst>(I))
      return updateWithSelectInst(A, SI);

    if (auto *CI = dyn_cast<CastInst>(I))
      return updateWithCastInst(A, CI);

    if (auto *BinOp = dyn_cast<BinaryOperator>(I))
      return updateWithBinaryOperator(A, BinOp);

    if (isa<PHINode>(I) || isa<LoadInst>(I))
      return updateWithInstruction(A, I);

    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {
  AAPotentialConstantValuesFunction(const IRPosition &IRP, Attributor &A)
      : AAPotentialConstantValuesImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable(
        "AAPotentialConstantValues(Function|CallSite)::updateImpl will "
        "not be called");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FN_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {
  AAPotentialConstantValuesCallSite(const IRPosition &IRP, Attributor &A)
      : AAPotentialConstantValuesFunction(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CS_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesCallSiteReturned
    : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
                                     AAPotentialConstantValuesImpl> {
  AAPotentialConstantValuesCallSiteReturned(const IRPosition &IRP,
                                            Attributor &A)
      : AACallSiteReturnedFromReturned<AAPotentialConstantValues,
                                       AAPotentialConstantValuesImpl>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(potential_values)
  }
};

struct AAPotentialConstantValuesCallSiteArgument
    : AAPotentialConstantValuesFloating {
  AAPotentialConstantValuesCallSiteArgument(const IRPosition &IRP,
                                            Attributor &A)
      : AAPotentialConstantValuesFloating(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    AAPotentialConstantValuesImpl::initialize(A);
    if (isAtFixpoint())
      return;

    Value &V = getAssociatedValue();

    if (auto *C = dyn_cast<ConstantInt>(&V)) {
      unionAssumed(C->getValue());
      indicateOptimisticFixpoint();
      return;
    }

    if (isa<UndefValue>(&V)) {
      unionAssumedWithUndef();
      indicateOptimisticFixpoint();
      return;
    }
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    Value &V = getAssociatedValue();
    auto AssumedBefore = getAssumed();
    auto *AA = A.getAAFor<AAPotentialConstantValues>(
        *this, IRPosition::value(V), DepClassTy::REQUIRED);
    if (!AA)
      return indicatePessimisticFixpoint();
    const auto &S = AA->getAssumed();
    unionAssumed(S);
    return AssumedBefore == getAssumed() ? ChangeStatus::UNCHANGED
                                         : ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(potential_values)
  }
};
} // namespace

/// ------------------------ NoUndef Attribute ---------------------------------
bool AANoUndef::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {
  assert(ImpliedAttributeKind == Attribute::NoUndef &&
         "Unexpected attribute kind");
  if (A.hasAttr(IRP, {Attribute::NoUndef}, IgnoreSubsumingPositions,
                Attribute::NoUndef))
    return true;

  Value &Val = IRP.getAssociatedValue();
  if (IRP.getPositionKind() != IRPosition::IRP_RETURNED &&
      isGuaranteedNotToBeUndefOrPoison(&Val)) {
    LLVMContext &Ctx = Val.getContext();
    A.manifestAttrs(IRP, Attribute::get(Ctx, Attribute::NoUndef));
    return true;
  }

  return false;
}

namespace {
struct AANoUndefImpl : AANoUndef {
  AANoUndefImpl(const IRPosition &IRP, Attributor &A) : AANoUndef(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    Value &V = getAssociatedValue();
    if (isa<UndefValue>(V))
      indicatePessimisticFixpoint();
    assert(!isImpliedByIR(A, getIRPosition(), Attribute::NoUndef));
  }

  /// See followUsesInMBEC
  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
                       AANoUndef::StateType &State) {
    const Value *UseV = U->get();
    const DominatorTree *DT = nullptr;
    AssumptionCache *AC = nullptr;
    InformationCache &InfoCache = A.getInfoCache();
    if (Function *F = getAnchorScope()) {
      DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
      AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
    }
    State.setKnown(isGuaranteedNotToBeUndefOrPoison(UseV, AC, I, DT));
    bool TrackUse = false;
    // Track use for instructions which must produce undef or poison bits when
    // at least one operand contains such bits.
    if (isa<CastInst>(*I) || isa<GetElementPtrInst>(*I))
      TrackUse = true;
    return TrackUse;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return getAssumed() ? "noundef" : "may-undef-or-poison";
  }

  ChangeStatus manifest(Attributor &A) override {
    // We don't manifest noundef attribute for dead positions because the
    // associated values with dead positions would be replaced with undef
    // values.
    bool UsedAssumedInformation = false;
    if (A.isAssumedDead(getIRPosition(), nullptr, nullptr,
                        UsedAssumedInformation))
      return ChangeStatus::UNCHANGED;
    // A position whose simplified value does not have any value is
    // considered to be dead. We don't manifest noundef in such positions for
    // the same reason above.
    if (!A.getAssumedSimplified(getIRPosition(), *this, UsedAssumedInformation,
                                AA::Interprocedural)
             .has_value())
      return ChangeStatus::UNCHANGED;
    return AANoUndef::manifest(A);
  }
};

struct AANoUndefFloating : public AANoUndefImpl {
  AANoUndefFloating(const IRPosition &IRP, Attributor &A)
      : AANoUndefImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    AANoUndefImpl::initialize(A);
    if (!getState().isAtFixpoint())
      if (Instruction *CtxI = getCtxI())
        followUsesInMBEC(*this, A, getState(), *CtxI);
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto VisitValueCB = [&](const IRPosition &IRP) -> bool {
      bool IsKnownNoUndef;
      return AA::hasAssumedIRAttr<Attribute::NoUndef>(
          A, this, IRP, DepClassTy::REQUIRED, IsKnownNoUndef);
    };

    bool Stripped;
    bool UsedAssumedInformation = false;
    Value *AssociatedValue = &getAssociatedValue();
    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
                                      AA::AnyScope, UsedAssumedInformation))
      Stripped = false;
    else
      Stripped =
          Values.size() != 1 || Values.front().getValue() != AssociatedValue;

    if (!Stripped) {
      // If we haven't stripped anything we might still be able to use a
      // different AA, but only if the IRP changes. Effectively when we
      // interpret this not as a call site value but as a floating/argument
      // value.
      const IRPosition AVIRP = IRPosition::value(*AssociatedValue);
      if (AVIRP == getIRPosition() || !VisitValueCB(AVIRP))
        return indicatePessimisticFixpoint();
      return ChangeStatus::UNCHANGED;
    }

    for (const auto &VAC : Values)
      if (!VisitValueCB(IRPosition::value(*VAC.getValue())))
        return indicatePessimisticFixpoint();

    return ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
};

struct AANoUndefReturned final
    : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl,
                                   AANoUndef::StateType, false,
                                   Attribute::NoUndef> {
  AANoUndefReturned(const IRPosition &IRP, Attributor &A)
      : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl,
                                     AANoUndef::StateType, false,
                                     Attribute::NoUndef>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_FNRET_ATTR(noundef) }
};

struct AANoUndefArgument final
    : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl,
                                      AANoUndef::StateType, false,
                                      Attribute::NoUndef> {
  AANoUndefArgument(const IRPosition &IRP, Attributor &A)
      : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl,
                                        AANoUndef::StateType, false,
                                        Attribute::NoUndef>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(noundef) }
};

struct AANoUndefCallSiteArgument final : AANoUndefFloating {
  AANoUndefCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANoUndefFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSARG_ATTR(noundef) }
};

struct AANoUndefCallSiteReturned final
    : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl,
                                     AANoUndef::StateType, false,
                                     Attribute::NoUndef> {
  AANoUndefCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AACallSiteReturnedFromReturned<AANoUndef, AANoUndefImpl,
                                       AANoUndef::StateType, false,
                                       Attribute::NoUndef>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_CSRET_ATTR(noundef) }
};

/// ------------------------ NoFPClass Attribute -------------------------------

struct AANoFPClassImpl : AANoFPClass {
  AANoFPClassImpl(const IRPosition &IRP, Attributor &A) : AANoFPClass(IRP, A) {}

  void initialize(Attributor &A) override {
    const IRPosition &IRP = getIRPosition();

    Value &V = IRP.getAssociatedValue();
    if (isa<UndefValue>(V)) {
      indicateOptimisticFixpoint();
      return;
    }

    SmallVector<Attribute> Attrs;
    A.getAttrs(getIRPosition(), {Attribute::NoFPClass}, Attrs, false);
    for (const auto &Attr : Attrs) {
      addKnownBits(Attr.getNoFPClass());
      return;
    }

    const DataLayout &DL = A.getDataLayout();
    if (getPositionKind() != IRPosition::IRP_RETURNED) {
      KnownFPClass KnownFPClass = computeKnownFPClass(&V, DL);
      addKnownBits(~KnownFPClass.KnownFPClasses);
    }

    if (Instruction *CtxI = getCtxI())
      followUsesInMBEC(*this, A, getState(), *CtxI);
  }

  /// See followUsesInMBEC
  bool followUseInMBEC(Attributor &A, const Use *U, const Instruction *I,
                       AANoFPClass::StateType &State) {
    const Value *UseV = U->get();
    const DominatorTree *DT = nullptr;
    AssumptionCache *AC = nullptr;
    const TargetLibraryInfo *TLI = nullptr;
    InformationCache &InfoCache = A.getInfoCache();

    if (Function *F = getAnchorScope()) {
      DT = InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
      AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);
      TLI = InfoCache.getTargetLibraryInfoForFunction(*F);
    }

    const DataLayout &DL = A.getDataLayout();

    KnownFPClass KnownFPClass =
        computeKnownFPClass(UseV, DL,
                            /*InterestedClasses=*/fcAllFlags,
                            /*Depth=*/0, TLI, AC, I, DT);
    State.addKnownBits(~KnownFPClass.KnownFPClasses);

    bool TrackUse = false;
    return TrackUse;
  }

  const std::string getAsStr(Attributor *A) const override {
    std::string Result = "nofpclass";
    raw_string_ostream OS(Result);
    OS << getAssumedNoFPClass();
    return Result;
  }

  void getDeducedAttributes(Attributor &A, LLVMContext &Ctx,
                            SmallVectorImpl<Attribute> &Attrs) const override {
    Attrs.emplace_back(Attribute::getWithNoFPClass(Ctx, getAssumedNoFPClass()));
  }
};

struct AANoFPClassFloating : public AANoFPClassImpl {
  AANoFPClassFloating(const IRPosition &IRP, Attributor &A)
      : AANoFPClassImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    SmallVector<AA::ValueAndContext> Values;
    bool UsedAssumedInformation = false;
    if (!A.getAssumedSimplifiedValues(getIRPosition(), *this, Values,
                                      AA::AnyScope, UsedAssumedInformation)) {
      Values.push_back({getAssociatedValue(), getCtxI()});
    }

    StateType T;
    auto VisitValueCB = [&](Value &V, const Instruction *CtxI) -> bool {
      const auto *AA = A.getAAFor<AANoFPClass>(*this, IRPosition::value(V),
                                               DepClassTy::REQUIRED);
      if (!AA || this == AA) {
        T.indicatePessimisticFixpoint();
      } else {
        const AANoFPClass::StateType &S =
            static_cast<const AANoFPClass::StateType &>(AA->getState());
        T ^= S;
      }
      return T.isValidState();
    };

    for (const auto &VAC : Values)
      if (!VisitValueCB(*VAC.getValue(), VAC.getCtxI()))
        return indicatePessimisticFixpoint();

    return clampStateAndIndicateChange(getState(), T);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(nofpclass)
  }
};

struct AANoFPClassReturned final
    : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
                                   AANoFPClassImpl::StateType, false, Attribute::None, false> {
  AANoFPClassReturned(const IRPosition &IRP, Attributor &A)
      : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
                                     AANoFPClassImpl::StateType, false, Attribute::None, false>(
            IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(nofpclass)
  }
};

struct AANoFPClassArgument final
    : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {
  AANoFPClassArgument(const IRPosition &IRP, Attributor &A)
      : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(nofpclass) }
};

struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {
  AANoFPClassCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AANoFPClassFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(nofpclass)
  }
};

struct AANoFPClassCallSiteReturned final
    : AACallSiteReturnedFromReturned<AANoFPClass, AANoFPClassImpl> {
  AANoFPClassCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AACallSiteReturnedFromReturned<AANoFPClass, AANoFPClassImpl>(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(nofpclass)
  }
};

struct AACallEdgesImpl : public AACallEdges {
  AACallEdgesImpl(const IRPosition &IRP, Attributor &A) : AACallEdges(IRP, A) {}

  const SetVector<Function *> &getOptimisticEdges() const override {
    return CalledFunctions;
  }

  bool hasUnknownCallee() const override { return HasUnknownCallee; }

  bool hasNonAsmUnknownCallee() const override {
    return HasUnknownCalleeNonAsm;
  }

  const std::string getAsStr(Attributor *A) const override {
    return "CallEdges[" + std::to_string(HasUnknownCallee) + "," +
           std::to_string(CalledFunctions.size()) + "]";
  }

  void trackStatistics() const override {}

protected:
  void addCalledFunction(Function *Fn, ChangeStatus &Change) {
    if (CalledFunctions.insert(Fn)) {
      Change = ChangeStatus::CHANGED;
      LLVM_DEBUG(dbgs() << "[AACallEdges] New call edge: " << Fn->getName()
                        << "\n");
    }
  }

  void setHasUnknownCallee(bool NonAsm, ChangeStatus &Change) {
    if (!HasUnknownCallee)
      Change = ChangeStatus::CHANGED;
    if (NonAsm && !HasUnknownCalleeNonAsm)
      Change = ChangeStatus::CHANGED;
    HasUnknownCalleeNonAsm |= NonAsm;
    HasUnknownCallee = true;
  }

private:
  /// Optimistic set of functions that might be called by this position.
  SetVector<Function *> CalledFunctions;

  /// Is there any call with a unknown callee.
  bool HasUnknownCallee = false;

  /// Is there any call with a unknown callee, excluding any inline asm.
  bool HasUnknownCalleeNonAsm = false;
};

struct AACallEdgesCallSite : public AACallEdgesImpl {
  AACallEdgesCallSite(const IRPosition &IRP, Attributor &A)
      : AACallEdgesImpl(IRP, A) {}
  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Change = ChangeStatus::UNCHANGED;

    auto VisitValue = [&](Value &V, const Instruction *CtxI) -> bool {
      if (Function *Fn = dyn_cast<Function>(&V)) {
        addCalledFunction(Fn, Change);
      } else {
        LLVM_DEBUG(dbgs() << "[AACallEdges] Unrecognized value: " << V << "\n");
        setHasUnknownCallee(true, Change);
      }

      // Explore all values.
      return true;
    };

    SmallVector<AA::ValueAndContext> Values;
    // Process any value that we might call.
    auto ProcessCalledOperand = [&](Value *V, Instruction *CtxI) {
      if (isa<Constant>(V)) {
        VisitValue(*V, CtxI);
        return;
      }

      bool UsedAssumedInformation = false;
      Values.clear();
      if (!A.getAssumedSimplifiedValues(IRPosition::value(*V), *this, Values,
                                        AA::AnyScope, UsedAssumedInformation)) {
        Values.push_back({*V, CtxI});
      }
      for (auto &VAC : Values)
        VisitValue(*VAC.getValue(), VAC.getCtxI());
    };

    CallBase *CB = cast<CallBase>(getCtxI());

    if (auto *IA = dyn_cast<InlineAsm>(CB->getCalledOperand())) {
      if (IA->hasSideEffects() &&
          !hasAssumption(*CB->getCaller(), "ompx_no_call_asm") &&
          !hasAssumption(*CB, "ompx_no_call_asm")) {
        setHasUnknownCallee(false, Change);
      }
      return Change;
    }

    // Process callee metadata if available.
    if (auto *MD = getCtxI()->getMetadata(LLVMContext::MD_callees)) {
      for (const auto &Op : MD->operands()) {
        Function *Callee = mdconst::dyn_extract_or_null<Function>(Op);
        if (Callee)
          addCalledFunction(Callee, Change);
      }
      return Change;
    }

    // The most simple case.
    ProcessCalledOperand(CB->getCalledOperand(), CB);

    // Process callback functions.
    SmallVector<const Use *, 4u> CallbackUses;
    AbstractCallSite::getCallbackUses(*CB, CallbackUses);
    for (const Use *U : CallbackUses)
      ProcessCalledOperand(U->get(), CB);

    return Change;
  }
};

struct AACallEdgesFunction : public AACallEdgesImpl {
  AACallEdgesFunction(const IRPosition &IRP, Attributor &A)
      : AACallEdgesImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    ChangeStatus Change = ChangeStatus::UNCHANGED;

    auto ProcessCallInst = [&](Instruction &Inst) {
      CallBase &CB = cast<CallBase>(Inst);

      auto *CBEdges = A.getAAFor<AACallEdges>(
          *this, IRPosition::callsite_function(CB), DepClassTy::REQUIRED);
      if (!CBEdges)
        return false;
      if (CBEdges->hasNonAsmUnknownCallee())
        setHasUnknownCallee(true, Change);
      if (CBEdges->hasUnknownCallee())
        setHasUnknownCallee(false, Change);

      for (Function *F : CBEdges->getOptimisticEdges())
        addCalledFunction(F, Change);

      return true;
    };

    // Visit all callable instructions.
    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallLikeInstructions(ProcessCallInst, *this,
                                           UsedAssumedInformation,
                                           /* CheckBBLivenessOnly */ true)) {
      // If we haven't looked at all call like instructions, assume that there
      // are unknown callees.
      setHasUnknownCallee(true, Change);
    }

    return Change;
  }
};

/// -------------------AAInterFnReachability Attribute--------------------------

struct AAInterFnReachabilityFunction
    : public CachedReachabilityAA<AAInterFnReachability, Function> {
  using Base = CachedReachabilityAA<AAInterFnReachability, Function>;
  AAInterFnReachabilityFunction(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  bool instructionCanReach(
      Attributor &A, const Instruction &From, const Function &To,
      const AA::InstExclusionSetTy *ExclusionSet,
      SmallPtrSet<const Function *, 16> *Visited) const override {
    assert(From.getFunction() == getAnchorScope() && "Queried the wrong AA!");
    auto *NonConstThis = const_cast<AAInterFnReachabilityFunction *>(this);

    RQITy StackRQI(A, From, To, ExclusionSet, false);
    typename RQITy::Reachable Result;
    if (!NonConstThis->checkQueryCache(A, StackRQI, Result))
      return NonConstThis->isReachableImpl(A, StackRQI);
    return Result == RQITy::Reachable::Yes;
  }

  bool isReachableImpl(Attributor &A, RQITy &RQI) override {
    return isReachableImpl(A, RQI, nullptr);
  }

  bool isReachableImpl(Attributor &A, RQITy &RQI,
                       SmallPtrSet<const Function *, 16> *Visited) {

    SmallPtrSet<const Function *, 16> LocalVisited;
    if (!Visited)
      Visited = &LocalVisited;

    auto CheckReachableCallBase = [&](CallBase *CB) {
      auto *CBEdges = A.getAAFor<AACallEdges>(
          *this, IRPosition::callsite_function(*CB), DepClassTy::OPTIONAL);
      if (!CBEdges || !CBEdges->getState().isValidState())
        return false;
      // TODO Check To backwards in this case.
      if (CBEdges->hasUnknownCallee())
        return false;

      for (Function *Fn : CBEdges->getOptimisticEdges()) {
        if (Fn == RQI.To)
          return false;
        if (!Visited->insert(Fn).second)
          continue;
        if (Fn->isDeclaration()) {
          if (Fn->hasFnAttribute(Attribute::NoCallback))
            continue;
          // TODO Check To backwards in this case.
          return false;
        }

        const AAInterFnReachability *InterFnReachability = this;
        if (Fn != getAnchorScope())
          InterFnReachability = A.getAAFor<AAInterFnReachability>(
              *this, IRPosition::function(*Fn), DepClassTy::OPTIONAL);

        const Instruction &FnFirstInst = Fn->getEntryBlock().front();
        if (!InterFnReachability ||
            InterFnReachability->instructionCanReach(A, FnFirstInst, *RQI.To,
                                                     RQI.ExclusionSet, Visited))
          return false;
      }
      return true;
    };

    const auto *IntraFnReachability = A.getAAFor<AAIntraFnReachability>(
        *this, IRPosition::function(*RQI.From->getFunction()),
        DepClassTy::OPTIONAL);

    // Determine call like instructions that we can reach from the inst.
    auto CheckCallBase = [&](Instruction &CBInst) {
      if (!IntraFnReachability || !IntraFnReachability->isAssumedReachable(
                                      A, *RQI.From, CBInst, RQI.ExclusionSet))
        return true;
      return CheckReachableCallBase(cast<CallBase>(&CBInst));
    };

    bool UsedExclusionSet = /* conservative */ true;
    bool UsedAssumedInformation = false;
    if (!A.checkForAllCallLikeInstructions(CheckCallBase, *this,
                                           UsedAssumedInformation,
                                           /* CheckBBLivenessOnly */ true))
      return rememberResult(A, RQITy::Reachable::Yes, RQI, UsedExclusionSet);

    return rememberResult(A, RQITy::Reachable::No, RQI, UsedExclusionSet);
  }

  void trackStatistics() const override {}

private:
  SmallVector<RQITy *> QueryVector;
  DenseSet<RQITy *> QueryCache;
};
} // namespace

template <typename AAType>
static std::optional<Constant *>
askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
                      const IRPosition &IRP, Type &Ty) {
  if (!Ty.isIntegerTy())
    return nullptr;

  // This will also pass the call base context.
  const auto *AA = A.getAAFor<AAType>(QueryingAA, IRP, DepClassTy::NONE);
  if (!AA)
    return nullptr;

  std::optional<Constant *> COpt = AA->getAssumedConstant(A);

  if (!COpt.has_value()) {
    A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
    return std::nullopt;
  }
  if (auto *C = *COpt) {
    A.recordDependence(*AA, QueryingAA, DepClassTy::OPTIONAL);
    return C;
  }
  return nullptr;
}

Value *AAPotentialValues::getSingleValue(
    Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
    SmallVectorImpl<AA::ValueAndContext> &Values) {
  Type &Ty = *IRP.getAssociatedType();
  std::optional<Value *> V;
  for (auto &It : Values) {
    V = AA::combineOptionalValuesInAAValueLatice(V, It.getValue(), &Ty);
    if (V.has_value() && !*V)
      break;
  }
  if (!V.has_value())
    return UndefValue::get(&Ty);
  return *V;
}

namespace {
struct AAPotentialValuesImpl : AAPotentialValues {
  using StateType = PotentialLLVMValuesState;

  AAPotentialValuesImpl(const IRPosition &IRP, Attributor &A)
      : AAPotentialValues(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    if (A.hasSimplificationCallback(getIRPosition())) {
      indicatePessimisticFixpoint();
      return;
    }
    Value *Stripped = getAssociatedValue().stripPointerCasts();
    auto *CE = dyn_cast<ConstantExpr>(Stripped);
    if (isa<Constant>(Stripped) &&
        (!CE || CE->getOpcode() != Instruction::ICmp)) {
      addValue(A, getState(), *Stripped, getCtxI(), AA::AnyScope,
               getAnchorScope());
      indicateOptimisticFixpoint();
      return;
    }
    AAPotentialValues::initialize(A);
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    std::string Str;
    llvm::raw_string_ostream OS(Str);
    OS << getState();
    return OS.str();
  }

  template <typename AAType>
  static std::optional<Value *> askOtherAA(Attributor &A,
                                           const AbstractAttribute &AA,
                                           const IRPosition &IRP, Type &Ty) {
    if (isa<Constant>(IRP.getAssociatedValue()))
      return &IRP.getAssociatedValue();
    std::optional<Constant *> C = askForAssumedConstant<AAType>(A, AA, IRP, Ty);
    if (!C)
      return std::nullopt;
    if (*C)
      if (auto *CC = AA::getWithType(**C, Ty))
        return CC;
    return nullptr;
  }

  virtual void addValue(Attributor &A, StateType &State, Value &V,
                        const Instruction *CtxI, AA::ValueScope S,
                        Function *AnchorScope) const {

    IRPosition ValIRP = IRPosition::value(V);
    if (auto *CB = dyn_cast_or_null<CallBase>(CtxI)) {
      for (const auto &U : CB->args()) {
        if (U.get() != &V)
          continue;
        ValIRP = IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
        break;
      }
    }

    Value *VPtr = &V;
    if (ValIRP.getAssociatedType()->isIntegerTy()) {
      Type &Ty = *getAssociatedType();
      std::optional<Value *> SimpleV =
          askOtherAA<AAValueConstantRange>(A, *this, ValIRP, Ty);
      if (SimpleV.has_value() && !*SimpleV) {
        auto *PotentialConstantsAA = A.getAAFor<AAPotentialConstantValues>(
            *this, ValIRP, DepClassTy::OPTIONAL);
        if (PotentialConstantsAA && PotentialConstantsAA->isValidState()) {
          for (const auto &It : PotentialConstantsAA->getAssumedSet())
            State.unionAssumed({{*ConstantInt::get(&Ty, It), nullptr}, S});
          if (PotentialConstantsAA->undefIsContained())
            State.unionAssumed({{*UndefValue::get(&Ty), nullptr}, S});
          return;
        }
      }
      if (!SimpleV.has_value())
        return;

      if (*SimpleV)
        VPtr = *SimpleV;
    }

    if (isa<ConstantInt>(VPtr))
      CtxI = nullptr;
    if (!AA::isValidInScope(*VPtr, AnchorScope))
      S = AA::ValueScope(S | AA::Interprocedural);

    State.unionAssumed({{*VPtr, CtxI}, S});
  }

  /// Helper struct to tie a value+context pair together with the scope for
  /// which this is the simplified version.
  struct ItemInfo {
    AA::ValueAndContext I;
    AA::ValueScope S;

    bool operator==(const ItemInfo &II) const {
      return II.I == I && II.S == S;
    };
    bool operator<(const ItemInfo &II) const {
      if (I == II.I)
        return S < II.S;
      return I < II.I;
    };
  };

  bool recurseForValue(Attributor &A, const IRPosition &IRP, AA::ValueScope S) {
    SmallMapVector<AA::ValueAndContext, int, 8> ValueScopeMap;
    for (auto CS : {AA::Intraprocedural, AA::Interprocedural}) {
      if (!(CS & S))
        continue;

      bool UsedAssumedInformation = false;
      SmallVector<AA::ValueAndContext> Values;
      if (!A.getAssumedSimplifiedValues(IRP, this, Values, CS,
                                        UsedAssumedInformation))
        return false;

      for (auto &It : Values)
        ValueScopeMap[It] += CS;
    }
    for (auto &It : ValueScopeMap)
      addValue(A, getState(), *It.first.getValue(), It.first.getCtxI(),
               AA::ValueScope(It.second), getAnchorScope());

    return true;
  }

  void giveUpOnIntraprocedural(Attributor &A) {
    auto NewS = StateType::getBestState(getState());
    for (const auto &It : getAssumedSet()) {
      if (It.second == AA::Intraprocedural)
        continue;
      addValue(A, NewS, *It.first.getValue(), It.first.getCtxI(),
               AA::Interprocedural, getAnchorScope());
    }
    assert(!undefIsContained() && "Undef should be an explicit value!");
    addValue(A, NewS, getAssociatedValue(), getCtxI(), AA::Intraprocedural,
             getAnchorScope());
    getState() = NewS;
  }

  /// See AbstractState::indicatePessimisticFixpoint(...).
  ChangeStatus indicatePessimisticFixpoint() override {
    getState() = StateType::getBestState(getState());
    getState().unionAssumed({{getAssociatedValue(), getCtxI()}, AA::AnyScope});
    AAPotentialValues::indicateOptimisticFixpoint();
    return ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    return indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    SmallVector<AA::ValueAndContext> Values;
    for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
      Values.clear();
      if (!getAssumedSimplifiedValues(A, Values, S))
        continue;
      Value &OldV = getAssociatedValue();
      if (isa<UndefValue>(OldV))
        continue;
      Value *NewV = getSingleValue(A, *this, getIRPosition(), Values);
      if (!NewV || NewV == &OldV)
        continue;
      if (getCtxI() &&
          !AA::isValidAtPosition({*NewV, *getCtxI()}, A.getInfoCache()))
        continue;
      if (A.changeAfterManifest(getIRPosition(), *NewV))
        return ChangeStatus::CHANGED;
    }
    return ChangeStatus::UNCHANGED;
  }

  bool getAssumedSimplifiedValues(
      Attributor &A, SmallVectorImpl<AA::ValueAndContext> &Values,
      AA::ValueScope S, bool RecurseForSelectAndPHI = false) const override {
    if (!isValidState())
      return false;
    bool UsedAssumedInformation = false;
    for (const auto &It : getAssumedSet())
      if (It.second & S) {
        if (RecurseForSelectAndPHI && (isa<PHINode>(It.first.getValue()) ||
                                       isa<SelectInst>(It.first.getValue()))) {
          if (A.getAssumedSimplifiedValues(
                  IRPosition::inst(*cast<Instruction>(It.first.getValue())),
                  this, Values, S, UsedAssumedInformation))
            continue;
        }
        Values.push_back(It.first);
      }
    assert(!undefIsContained() && "Undef should be an explicit value!");
    return true;
  }
};

struct AAPotentialValuesFloating : AAPotentialValuesImpl {
  AAPotentialValuesFloating(const IRPosition &IRP, Attributor &A)
      : AAPotentialValuesImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto AssumedBefore = getAssumed();

    genericValueTraversal(A, &getAssociatedValue());

    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
                                           : ChangeStatus::CHANGED;
  }

  /// Helper struct to remember which AAIsDead instances we actually used.
  struct LivenessInfo {
    const AAIsDead *LivenessAA = nullptr;
    bool AnyDead = false;
  };

  /// Check if \p Cmp is a comparison we can simplify.
  ///
  /// We handle multiple cases, one in which at least one operand is an
  /// (assumed) nullptr. If so, try to simplify it using AANonNull on the other
  /// operand. Return true if successful, in that case Worklist will be updated.
  bool handleCmp(Attributor &A, Value &Cmp, Value *LHS, Value *RHS,
                 CmpInst::Predicate Pred, ItemInfo II,
                 SmallVectorImpl<ItemInfo> &Worklist) {

    // Simplify the operands first.
    bool UsedAssumedInformation = false;
    const auto &SimplifiedLHS = A.getAssumedSimplified(
        IRPosition::value(*LHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Intraprocedural);
    if (!SimplifiedLHS.has_value())
      return true;
    if (!*SimplifiedLHS)
      return false;
    LHS = *SimplifiedLHS;

    const auto &SimplifiedRHS = A.getAssumedSimplified(
        IRPosition::value(*RHS, getCallBaseContext()), *this,
        UsedAssumedInformation, AA::Intraprocedural);
    if (!SimplifiedRHS.has_value())
      return true;
    if (!*SimplifiedRHS)
      return false;
    RHS = *SimplifiedRHS;

    LLVMContext &Ctx = LHS->getContext();
    // Handle the trivial case first in which we don't even need to think about
    // null or non-null.
    if (LHS == RHS &&
        (CmpInst::isTrueWhenEqual(Pred) || CmpInst::isFalseWhenEqual(Pred))) {
      Constant *NewV = ConstantInt::get(Type::getInt1Ty(Ctx),
                                        CmpInst::isTrueWhenEqual(Pred));
      addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S,
               getAnchorScope());
      return true;
    }

    // From now on we only handle equalities (==, !=).
    if (!CmpInst::isEquality(Pred))
      return false;

    bool LHSIsNull = isa<ConstantPointerNull>(LHS);
    bool RHSIsNull = isa<ConstantPointerNull>(RHS);
    if (!LHSIsNull && !RHSIsNull)
      return false;

    // Left is the nullptr ==/!= non-nullptr case. We'll use AANonNull on the
    // non-nullptr operand and if we assume it's non-null we can conclude the
    // result of the comparison.
    assert((LHSIsNull || RHSIsNull) &&
           "Expected nullptr versus non-nullptr comparison at this point");

    // The index is the operand that we assume is not null.
    unsigned PtrIdx = LHSIsNull;
    bool IsKnownNonNull;
    bool IsAssumedNonNull = AA::hasAssumedIRAttr<Attribute::NonNull>(
        A, this, IRPosition::value(*(PtrIdx ? RHS : LHS)), DepClassTy::REQUIRED,
        IsKnownNonNull);
    if (!IsAssumedNonNull)
      return false;

    // The new value depends on the predicate, true for != and false for ==.
    Constant *NewV =
        ConstantInt::get(Type::getInt1Ty(Ctx), Pred == CmpInst::ICMP_NE);
    addValue(A, getState(), *NewV, /* CtxI */ nullptr, II.S, getAnchorScope());
    return true;
  }

  bool handleSelectInst(Attributor &A, SelectInst &SI, ItemInfo II,
                        SmallVectorImpl<ItemInfo> &Worklist) {
    const Instruction *CtxI = II.I.getCtxI();
    bool UsedAssumedInformation = false;

    std::optional<Constant *> C =
        A.getAssumedConstant(*SI.getCondition(), *this, UsedAssumedInformation);
    bool NoValueYet = !C.has_value();
    if (NoValueYet || isa_and_nonnull<UndefValue>(*C))
      return true;
    if (auto *CI = dyn_cast_or_null<ConstantInt>(*C)) {
      if (CI->isZero())
        Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
      else
        Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
    } else if (&SI == &getAssociatedValue()) {
      // We could not simplify the condition, assume both values.
      Worklist.push_back({{*SI.getTrueValue(), CtxI}, II.S});
      Worklist.push_back({{*SI.getFalseValue(), CtxI}, II.S});
    } else {
      std::optional<Value *> SimpleV = A.getAssumedSimplified(
          IRPosition::inst(SI), *this, UsedAssumedInformation, II.S);
      if (!SimpleV.has_value())
        return true;
      if (*SimpleV) {
        addValue(A, getState(), **SimpleV, CtxI, II.S, getAnchorScope());
        return true;
      }
      return false;
    }
    return true;
  }

  bool handleLoadInst(Attributor &A, LoadInst &LI, ItemInfo II,
                      SmallVectorImpl<ItemInfo> &Worklist) {
    SmallSetVector<Value *, 4> PotentialCopies;
    SmallSetVector<Instruction *, 4> PotentialValueOrigins;
    bool UsedAssumedInformation = false;
    if (!AA::getPotentiallyLoadedValues(A, LI, PotentialCopies,
                                        PotentialValueOrigins, *this,
                                        UsedAssumedInformation,
                                        /* OnlyExact */ true)) {
      LLVM_DEBUG(dbgs() << "[AAPotentialValues] Failed to get potentially "
                           "loaded values for load instruction "
                        << LI << "\n");
      return false;
    }

    // Do not simplify loads that are only used in llvm.assume if we cannot also
    // remove all stores that may feed into the load. The reason is that the
    // assume is probably worth something as long as the stores are around.
    InformationCache &InfoCache = A.getInfoCache();
    if (InfoCache.isOnlyUsedByAssume(LI)) {
      if (!llvm::all_of(PotentialValueOrigins, [&](Instruction *I) {
            if (!I || isa<AssumeInst>(I))
              return true;
            if (auto *SI = dyn_cast<StoreInst>(I))
              return A.isAssumedDead(SI->getOperandUse(0), this,
                                     /* LivenessAA */ nullptr,
                                     UsedAssumedInformation,
                                     /* CheckBBLivenessOnly */ false);
            return A.isAssumedDead(*I, this, /* LivenessAA */ nullptr,
                                   UsedAssumedInformation,
                                   /* CheckBBLivenessOnly */ false);
          })) {
        LLVM_DEBUG(dbgs() << "[AAPotentialValues] Load is onl used by assumes "
                             "and we cannot delete all the stores: "
                          << LI << "\n");
        return false;
      }
    }

    // Values have to be dynamically unique or we loose the fact that a
    // single llvm::Value might represent two runtime values (e.g.,
    // stack locations in different recursive calls).
    const Instruction *CtxI = II.I.getCtxI();
    bool ScopeIsLocal = (II.S & AA::Intraprocedural);
    bool AllLocal = ScopeIsLocal;
    bool DynamicallyUnique = llvm::all_of(PotentialCopies, [&](Value *PC) {
      AllLocal &= AA::isValidInScope(*PC, getAnchorScope());
      return AA::isDynamicallyUnique(A, *this, *PC);
    });
    if (!DynamicallyUnique) {
      LLVM_DEBUG(dbgs() << "[AAPotentialValues] Not all potentially loaded "
                           "values are dynamically unique: "
                        << LI << "\n");
      return false;
    }

    for (auto *PotentialCopy : PotentialCopies) {
      if (AllLocal) {
        Worklist.push_back({{*PotentialCopy, CtxI}, II.S});
      } else {
        Worklist.push_back({{*PotentialCopy, CtxI}, AA::Interprocedural});
      }
    }
    if (!AllLocal && ScopeIsLocal)
      addValue(A, getState(), LI, CtxI, AA::Intraprocedural, getAnchorScope());
    return true;
  }

  bool handlePHINode(
      Attributor &A, PHINode &PHI, ItemInfo II,
      SmallVectorImpl<ItemInfo> &Worklist,
      SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
    auto GetLivenessInfo = [&](const Function &F) -> LivenessInfo & {
      LivenessInfo &LI = LivenessAAs[&F];
      if (!LI.LivenessAA)
        LI.LivenessAA = A.getAAFor<AAIsDead>(*this, IRPosition::function(F),
                                             DepClassTy::NONE);
      return LI;
    };

    if (&PHI == &getAssociatedValue()) {
      LivenessInfo &LI = GetLivenessInfo(*PHI.getFunction());
      const auto *CI =
          A.getInfoCache().getAnalysisResultForFunction<CycleAnalysis>(
              *PHI.getFunction());

      Cycle *C = nullptr;
      bool CyclePHI = mayBeInCycle(CI, &PHI, /* HeaderOnly */ true, &C);
      for (unsigned u = 0, e = PHI.getNumIncomingValues(); u < e; u++) {
        BasicBlock *IncomingBB = PHI.getIncomingBlock(u);
        if (LI.LivenessAA &&
            LI.LivenessAA->isEdgeDead(IncomingBB, PHI.getParent())) {
          LI.AnyDead = true;
          continue;
        }
        Value *V = PHI.getIncomingValue(u);
        if (V == &PHI)
          continue;

        // If the incoming value is not the PHI but an instruction in the same
        // cycle we might have multiple versions of it flying around.
        if (CyclePHI && isa<Instruction>(V) &&
            (!C || C->contains(cast<Instruction>(V)->getParent())))
          return false;

        Worklist.push_back({{*V, IncomingBB->getTerminator()}, II.S});
      }
      return true;
    }

    bool UsedAssumedInformation = false;
    std::optional<Value *> SimpleV = A.getAssumedSimplified(
        IRPosition::inst(PHI), *this, UsedAssumedInformation, II.S);
    if (!SimpleV.has_value())
      return true;
    if (!(*SimpleV))
      return false;
    addValue(A, getState(), **SimpleV, &PHI, II.S, getAnchorScope());
    return true;
  }

  /// Use the generic, non-optimistic InstSimplfy functionality if we managed to
  /// simplify any operand of the instruction \p I. Return true if successful,
  /// in that case Worklist will be updated.
  bool handleGenericInst(Attributor &A, Instruction &I, ItemInfo II,
                         SmallVectorImpl<ItemInfo> &Worklist) {
    bool SomeSimplified = false;
    bool UsedAssumedInformation = false;

    SmallVector<Value *, 8> NewOps(I.getNumOperands());
    int Idx = 0;
    for (Value *Op : I.operands()) {
      const auto &SimplifiedOp = A.getAssumedSimplified(
          IRPosition::value(*Op, getCallBaseContext()), *this,
          UsedAssumedInformation, AA::Intraprocedural);
      // If we are not sure about any operand we are not sure about the entire
      // instruction, we'll wait.
      if (!SimplifiedOp.has_value())
        return true;

      if (*SimplifiedOp)
        NewOps[Idx] = *SimplifiedOp;
      else
        NewOps[Idx] = Op;

      SomeSimplified |= (NewOps[Idx] != Op);
      ++Idx;
    }

    // We won't bother with the InstSimplify interface if we didn't simplify any
    // operand ourselves.
    if (!SomeSimplified)
      return false;

    InformationCache &InfoCache = A.getInfoCache();
    Function *F = I.getFunction();
    const auto *DT =
        InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(*F);
    const auto *TLI = A.getInfoCache().getTargetLibraryInfoForFunction(*F);
    auto *AC = InfoCache.getAnalysisResultForFunction<AssumptionAnalysis>(*F);

    const DataLayout &DL = I.getModule()->getDataLayout();
    SimplifyQuery Q(DL, TLI, DT, AC, &I);
    Value *NewV = simplifyInstructionWithOperands(&I, NewOps, Q);
    if (!NewV || NewV == &I)
      return false;

    LLVM_DEBUG(dbgs() << "Generic inst " << I << " assumed simplified to "
                      << *NewV << "\n");
    Worklist.push_back({{*NewV, II.I.getCtxI()}, II.S});
    return true;
  }

  bool simplifyInstruction(
      Attributor &A, Instruction &I, ItemInfo II,
      SmallVectorImpl<ItemInfo> &Worklist,
      SmallMapVector<const Function *, LivenessInfo, 4> &LivenessAAs) {
    if (auto *CI = dyn_cast<CmpInst>(&I))
      if (handleCmp(A, *CI, CI->getOperand(0), CI->getOperand(1),
                    CI->getPredicate(), II, Worklist))
        return true;

    switch (I.getOpcode()) {
    case Instruction::Select:
      return handleSelectInst(A, cast<SelectInst>(I), II, Worklist);
    case Instruction::PHI:
      return handlePHINode(A, cast<PHINode>(I), II, Worklist, LivenessAAs);
    case Instruction::Load:
      return handleLoadInst(A, cast<LoadInst>(I), II, Worklist);
    default:
      return handleGenericInst(A, I, II, Worklist);
    };
    return false;
  }

  void genericValueTraversal(Attributor &A, Value *InitialV) {
    SmallMapVector<const Function *, LivenessInfo, 4> LivenessAAs;

    SmallSet<ItemInfo, 16> Visited;
    SmallVector<ItemInfo, 16> Worklist;
    Worklist.push_back({{*InitialV, getCtxI()}, AA::AnyScope});

    int Iteration = 0;
    do {
      ItemInfo II = Worklist.pop_back_val();
      Value *V = II.I.getValue();
      assert(V);
      const Instruction *CtxI = II.I.getCtxI();
      AA::ValueScope S = II.S;

      // Check if we should process the current value. To prevent endless
      // recursion keep a record of the values we followed!
      if (!Visited.insert(II).second)
        continue;

      // Make sure we limit the compile time for complex expressions.
      if (Iteration++ >= MaxPotentialValuesIterations) {
        LLVM_DEBUG(dbgs() << "Generic value traversal reached iteration limit: "
                          << Iteration << "!\n");
        addValue(A, getState(), *V, CtxI, S, getAnchorScope());
        continue;
      }

      // Explicitly look through calls with a "returned" attribute if we do
      // not have a pointer as stripPointerCasts only works on them.
      Value *NewV = nullptr;
      if (V->getType()->isPointerTy()) {
        NewV = AA::getWithType(*V->stripPointerCasts(), *V->getType());
      } else {
        if (auto *CB = dyn_cast<CallBase>(V))
          if (auto *Callee =
                  dyn_cast_if_present<Function>(CB->getCalledOperand())) {
            for (Argument &Arg : Callee->args())
              if (Arg.hasReturnedAttr()) {
                NewV = CB->getArgOperand(Arg.getArgNo());
                break;
              }
          }
      }
      if (NewV && NewV != V) {
        Worklist.push_back({{*NewV, CtxI}, S});
        continue;
      }

      if (auto *CE = dyn_cast<ConstantExpr>(V)) {
        if (CE->getOpcode() == Instruction::ICmp)
          if (handleCmp(A, *CE, CE->getOperand(0), CE->getOperand(1),
                        CmpInst::Predicate(CE->getPredicate()), II, Worklist))
            continue;
      }

      if (auto *I = dyn_cast<Instruction>(V)) {
        if (simplifyInstruction(A, *I, II, Worklist, LivenessAAs))
          continue;
      }

      if (V != InitialV || isa<Argument>(V))
        if (recurseForValue(A, IRPosition::value(*V), II.S))
          continue;

      // If we haven't stripped anything we give up.
      if (V == InitialV && CtxI == getCtxI()) {
        indicatePessimisticFixpoint();
        return;
      }

      addValue(A, getState(), *V, CtxI, S, getAnchorScope());
    } while (!Worklist.empty());

    // If we actually used liveness information so we have to record a
    // dependence.
    for (auto &It : LivenessAAs)
      if (It.second.AnyDead)
        A.recordDependence(*It.second.LivenessAA, *this, DepClassTy::OPTIONAL);
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(potential_values)
  }
};

struct AAPotentialValuesArgument final : AAPotentialValuesImpl {
  using Base = AAPotentialValuesImpl;
  AAPotentialValuesArgument(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    auto &Arg = cast<Argument>(getAssociatedValue());
    if (Arg.hasPointeeInMemoryValueAttr())
      indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto AssumedBefore = getAssumed();

    unsigned CSArgNo = getCallSiteArgNo();

    bool UsedAssumedInformation = false;
    SmallVector<AA::ValueAndContext> Values;
    auto CallSitePred = [&](AbstractCallSite ACS) {
      const auto CSArgIRP = IRPosition::callsite_argument(ACS, CSArgNo);
      if (CSArgIRP.getPositionKind() == IRP_INVALID)
        return false;

      if (!A.getAssumedSimplifiedValues(CSArgIRP, this, Values,
                                        AA::Interprocedural,
                                        UsedAssumedInformation))
        return false;

      return isValidState();
    };

    if (!A.checkForAllCallSites(CallSitePred, *this,
                                /* RequireAllCallSites */ true,
                                UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    Function *Fn = getAssociatedFunction();
    bool AnyNonLocal = false;
    for (auto &It : Values) {
      if (isa<Constant>(It.getValue())) {
        addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
                 getAnchorScope());
        continue;
      }
      if (!AA::isDynamicallyUnique(A, *this, *It.getValue()))
        return indicatePessimisticFixpoint();

      if (auto *Arg = dyn_cast<Argument>(It.getValue()))
        if (Arg->getParent() == Fn) {
          addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::AnyScope,
                   getAnchorScope());
          continue;
        }
      addValue(A, getState(), *It.getValue(), It.getCtxI(), AA::Interprocedural,
               getAnchorScope());
      AnyNonLocal = true;
    }
    assert(!undefIsContained() && "Undef should be an explicit value!");
    if (AnyNonLocal)
      giveUpOnIntraprocedural(A);

    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
                                           : ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_ARG_ATTR(potential_values)
  }
};

struct AAPotentialValuesReturned : public AAPotentialValuesFloating {
  using Base = AAPotentialValuesFloating;
  AAPotentialValuesReturned(const IRPosition &IRP, Attributor &A)
      : Base(IRP, A) {}

  /// See AbstractAttribute::initialize(..).
  void initialize(Attributor &A) override {
    Function *F = getAssociatedFunction();
    if (!F || F->isDeclaration() || F->getReturnType()->isVoidTy()) {
      indicatePessimisticFixpoint();
      return;
    }

    for (Argument &Arg : F->args())
      if (Arg.hasReturnedAttr()) {
        addValue(A, getState(), Arg, nullptr, AA::AnyScope, F);
        ReturnedArg = &Arg;
        break;
      }
    if (!A.isFunctionIPOAmendable(*F) ||
        A.hasSimplificationCallback(getIRPosition())) {
      if (!ReturnedArg)
        indicatePessimisticFixpoint();
      else
        indicateOptimisticFixpoint();
    }
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto AssumedBefore = getAssumed();
    bool UsedAssumedInformation = false;

    SmallVector<AA::ValueAndContext> Values;
    Function *AnchorScope = getAnchorScope();
    auto HandleReturnedValue = [&](Value &V, Instruction *CtxI,
                                   bool AddValues) {
      for (AA::ValueScope S : {AA::Interprocedural, AA::Intraprocedural}) {
        Values.clear();
        if (!A.getAssumedSimplifiedValues(IRPosition::value(V), this, Values, S,
                                          UsedAssumedInformation,
                                          /* RecurseForSelectAndPHI */ true))
          return false;
        if (!AddValues)
          continue;
        for (const AA::ValueAndContext &VAC : Values)
          addValue(A, getState(), *VAC.getValue(),
                   VAC.getCtxI() ? VAC.getCtxI() : CtxI, S, AnchorScope);
      }
      return true;
    };

    if (ReturnedArg) {
      HandleReturnedValue(*ReturnedArg, nullptr, true);
    } else {
      auto RetInstPred = [&](Instruction &RetI) {
        bool AddValues = true;
        if (isa<PHINode>(RetI.getOperand(0)) ||
            isa<SelectInst>(RetI.getOperand(0))) {
          addValue(A, getState(), *RetI.getOperand(0), &RetI, AA::AnyScope,
                   AnchorScope);
          AddValues = false;
        }
        return HandleReturnedValue(*RetI.getOperand(0), &RetI, AddValues);
      };

      if (!A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
                                     UsedAssumedInformation,
                                     /* CheckBBLivenessOnly */ true))
        return indicatePessimisticFixpoint();
    }

    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
                                           : ChangeStatus::CHANGED;
  }

  void addValue(Attributor &A, StateType &State, Value &V,
                const Instruction *CtxI, AA::ValueScope S,
                Function *AnchorScope) const override {
    Function *F = getAssociatedFunction();
    if (auto *CB = dyn_cast<CallBase>(&V))
      if (CB->getCalledOperand() == F)
        return;
    Base::addValue(A, State, V, CtxI, S, AnchorScope);
  }

  ChangeStatus manifest(Attributor &A) override {
    if (ReturnedArg)
      return ChangeStatus::UNCHANGED;
    SmallVector<AA::ValueAndContext> Values;
    if (!getAssumedSimplifiedValues(A, Values, AA::ValueScope::Intraprocedural,
                                    /* RecurseForSelectAndPHI */ true))
      return ChangeStatus::UNCHANGED;
    Value *NewVal = getSingleValue(A, *this, getIRPosition(), Values);
    if (!NewVal)
      return ChangeStatus::UNCHANGED;

    ChangeStatus Changed = ChangeStatus::UNCHANGED;
    if (auto *Arg = dyn_cast<Argument>(NewVal)) {
      STATS_DECLTRACK(UniqueReturnValue, FunctionReturn,
                      "Number of function with unique return");
      Changed |= A.manifestAttrs(
          IRPosition::argument(*Arg),
          {Attribute::get(Arg->getContext(), Attribute::Returned)});
      STATS_DECLTRACK_ARG_ATTR(returned);
    }

    auto RetInstPred = [&](Instruction &RetI) {
      Value *RetOp = RetI.getOperand(0);
      if (isa<UndefValue>(RetOp) || RetOp == NewVal)
        return true;
      if (AA::isValidAtPosition({*NewVal, RetI}, A.getInfoCache()))
        if (A.changeUseAfterManifest(RetI.getOperandUse(0), *NewVal))
          Changed = ChangeStatus::CHANGED;
      return true;
    };
    bool UsedAssumedInformation = false;
    (void)A.checkForAllInstructions(RetInstPred, *this, {Instruction::Ret},
                                    UsedAssumedInformation,
                                    /* CheckBBLivenessOnly */ true);
    return Changed;
  }

  ChangeStatus indicatePessimisticFixpoint() override {
    return AAPotentialValues::indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override{
      STATS_DECLTRACK_FNRET_ATTR(potential_values)}

  /// The argumented with an existing `returned` attribute.
  Argument *ReturnedArg = nullptr;
};

struct AAPotentialValuesFunction : AAPotentialValuesImpl {
  AAPotentialValuesFunction(const IRPosition &IRP, Attributor &A)
      : AAPotentialValuesImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    llvm_unreachable("AAPotentialValues(Function|CallSite)::updateImpl will "
                     "not be called");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_FN_ATTR(potential_values)
  }
};

struct AAPotentialValuesCallSite : AAPotentialValuesFunction {
  AAPotentialValuesCallSite(const IRPosition &IRP, Attributor &A)
      : AAPotentialValuesFunction(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CS_ATTR(potential_values)
  }
};

struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {
  AAPotentialValuesCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAPotentialValuesImpl(IRP, A) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto AssumedBefore = getAssumed();

    Function *Callee = getAssociatedFunction();
    if (!Callee)
      return indicatePessimisticFixpoint();

    bool UsedAssumedInformation = false;
    auto *CB = cast<CallBase>(getCtxI());
    if (CB->isMustTailCall() &&
        !A.isAssumedDead(IRPosition::inst(*CB), this, nullptr,
                         UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    SmallVector<AA::ValueAndContext> Values;
    if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
                                      Values, AA::Intraprocedural,
                                      UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    Function *Caller = CB->getCaller();

    bool AnyNonLocal = false;
    for (auto &It : Values) {
      Value *V = It.getValue();
      std::optional<Value *> CallerV = A.translateArgumentToCallSiteContent(
          V, *CB, *this, UsedAssumedInformation);
      if (!CallerV.has_value()) {
        // Nothing to do as long as no value was determined.
        continue;
      }
      V = *CallerV ? *CallerV : V;
      if (AA::isDynamicallyUnique(A, *this, *V) &&
          AA::isValidInScope(*V, Caller)) {
        if (*CallerV) {
          SmallVector<AA::ValueAndContext> ArgValues;
          IRPosition IRP = IRPosition::value(*V);
          if (auto *Arg = dyn_cast<Argument>(V))
            if (Arg->getParent() == CB->getCalledOperand())
              IRP = IRPosition::callsite_argument(*CB, Arg->getArgNo());
          if (recurseForValue(A, IRP, AA::AnyScope))
            continue;
        }
        addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
      } else {
        AnyNonLocal = true;
        break;
      }
    }
    if (AnyNonLocal) {
      Values.clear();
      if (!A.getAssumedSimplifiedValues(IRPosition::returned(*Callee), this,
                                        Values, AA::Interprocedural,
                                        UsedAssumedInformation))
        return indicatePessimisticFixpoint();
      AnyNonLocal = false;
      getState() = PotentialLLVMValuesState::getBestState();
      for (auto &It : Values) {
        Value *V = It.getValue();
        if (!AA::isDynamicallyUnique(A, *this, *V))
          return indicatePessimisticFixpoint();
        if (AA::isValidInScope(*V, Caller)) {
          addValue(A, getState(), *V, CB, AA::AnyScope, getAnchorScope());
        } else {
          AnyNonLocal = true;
          addValue(A, getState(), *V, CB, AA::Interprocedural,
                   getAnchorScope());
        }
      }
      if (AnyNonLocal)
        giveUpOnIntraprocedural(A);
    }
    return (AssumedBefore == getAssumed()) ? ChangeStatus::UNCHANGED
                                           : ChangeStatus::CHANGED;
  }

  ChangeStatus indicatePessimisticFixpoint() override {
    return AAPotentialValues::indicatePessimisticFixpoint();
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(potential_values)
  }
};

struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {
  AAPotentialValuesCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAPotentialValuesFloating(IRP, A) {}

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(potential_values)
  }
};
} // namespace

/// ---------------------- Assumption Propagation ------------------------------
namespace {
struct AAAssumptionInfoImpl : public AAAssumptionInfo {
  AAAssumptionInfoImpl(const IRPosition &IRP, Attributor &A,
                       const DenseSet<StringRef> &Known)
      : AAAssumptionInfo(IRP, A, Known) {}

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    // Don't manifest a universal set if it somehow made it here.
    if (getKnown().isUniversal())
      return ChangeStatus::UNCHANGED;

    const IRPosition &IRP = getIRPosition();
    return A.manifestAttrs(
        IRP,
        Attribute::get(IRP.getAnchorValue().getContext(), AssumptionAttrKey,
                       llvm::join(getAssumed().getSet(), ",")),
        /* ForceReplace */ true);
  }

  bool hasAssumption(const StringRef Assumption) const override {
    return isValidState() && setContains(Assumption);
  }

  /// See AbstractAttribute::getAsStr()
  const std::string getAsStr(Attributor *A) const override {
    const SetContents &Known = getKnown();
    const SetContents &Assumed = getAssumed();

    const std::string KnownStr =
        llvm::join(Known.getSet().begin(), Known.getSet().end(), ",");
    const std::string AssumedStr =
        (Assumed.isUniversal())
            ? "Universal"
            : llvm::join(Assumed.getSet().begin(), Assumed.getSet().end(), ",");

    return "Known [" + KnownStr + "]," + " Assumed [" + AssumedStr + "]";
  }
};

/// Propagates assumption information from parent functions to all of their
/// successors. An assumption can be propagated if the containing function
/// dominates the called function.
///
/// We start with a "known" set of assumptions already valid for the associated
/// function and an "assumed" set that initially contains all possible
/// assumptions. The assumed set is inter-procedurally updated by narrowing its
/// contents as concrete values are known. The concrete values are seeded by the
/// first nodes that are either entries into the call graph, or contains no
/// assumptions. Each node is updated as the intersection of the assumed state
/// with all of its predecessors.
struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {
  AAAssumptionInfoFunction(const IRPosition &IRP, Attributor &A)
      : AAAssumptionInfoImpl(IRP, A,
                             getAssumptions(*IRP.getAssociatedFunction())) {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    bool Changed = false;

    auto CallSitePred = [&](AbstractCallSite ACS) {
      const auto *AssumptionAA = A.getAAFor<AAAssumptionInfo>(
          *this, IRPosition::callsite_function(*ACS.getInstruction()),
          DepClassTy::REQUIRED);
      if (!AssumptionAA)
        return false;
      // Get the set of assumptions shared by all of this function's callers.
      Changed |= getIntersection(AssumptionAA->getAssumed());
      return !getAssumed().empty() || !getKnown().empty();
    };

    bool UsedAssumedInformation = false;
    // Get the intersection of all assumptions held by this node's predecessors.
    // If we don't know all the call sites then this is either an entry into the
    // call graph or an empty node. This node is known to only contain its own
    // assumptions and can be propagated to its successors.
    if (!A.checkForAllCallSites(CallSitePred, *this, true,
                                UsedAssumedInformation))
      return indicatePessimisticFixpoint();

    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  void trackStatistics() const override {}
};

/// Assumption Info defined for call sites.
struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {

  AAAssumptionInfoCallSite(const IRPosition &IRP, Attributor &A)
      : AAAssumptionInfoImpl(IRP, A, getInitialAssumptions(IRP)) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
    A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
  }

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    const IRPosition &FnPos = IRPosition::function(*getAnchorScope());
    auto *AssumptionAA =
        A.getAAFor<AAAssumptionInfo>(*this, FnPos, DepClassTy::REQUIRED);
    if (!AssumptionAA)
      return indicatePessimisticFixpoint();
    bool Changed = getIntersection(AssumptionAA->getAssumed());
    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}

private:
  /// Helper to initialized the known set as all the assumptions this call and
  /// the callee contain.
  DenseSet<StringRef> getInitialAssumptions(const IRPosition &IRP) {
    const CallBase &CB = cast<CallBase>(IRP.getAssociatedValue());
    auto Assumptions = getAssumptions(CB);
    if (const Function *F = CB.getCaller())
      set_union(Assumptions, getAssumptions(*F));
    if (Function *F = IRP.getAssociatedFunction())
      set_union(Assumptions, getAssumptions(*F));
    return Assumptions;
  }
};
} // namespace

AACallGraphNode *AACallEdgeIterator::operator*() const {
  return static_cast<AACallGraphNode *>(const_cast<AACallEdges *>(
      A.getOrCreateAAFor<AACallEdges>(IRPosition::function(**I))));
}

void AttributorCallGraph::print() { llvm::WriteGraph(outs(), this); }

/// ------------------------ UnderlyingObjects ---------------------------------

namespace {
struct AAUnderlyingObjectsImpl
    : StateWrapper<BooleanState, AAUnderlyingObjects> {
  using BaseTy = StateWrapper<BooleanState, AAUnderlyingObjects>;
  AAUnderlyingObjectsImpl(const IRPosition &IRP, Attributor &A) : BaseTy(IRP) {}

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    return std::string("UnderlyingObjects ") +
           (isValidState()
                ? (std::string("inter #") +
                   std::to_string(InterAssumedUnderlyingObjects.size()) +
                   " objs" + std::string(", intra #") +
                   std::to_string(IntraAssumedUnderlyingObjects.size()) +
                   " objs")
                : "<invalid>");
  }

  /// See AbstractAttribute::trackStatistics()
  void trackStatistics() const override {}

  /// See AbstractAttribute::updateImpl(...).
  ChangeStatus updateImpl(Attributor &A) override {
    auto &Ptr = getAssociatedValue();

    auto DoUpdate = [&](SmallSetVector<Value *, 8> &UnderlyingObjects,
                        AA::ValueScope Scope) {
      bool UsedAssumedInformation = false;
      SmallPtrSet<Value *, 8> SeenObjects;
      SmallVector<AA::ValueAndContext> Values;

      if (!A.getAssumedSimplifiedValues(IRPosition::value(Ptr), *this, Values,
                                        Scope, UsedAssumedInformation))
        return UnderlyingObjects.insert(&Ptr);

      bool Changed = false;

      for (unsigned I = 0; I < Values.size(); ++I) {
        auto &VAC = Values[I];
        auto *Obj = VAC.getValue();
        Value *UO = getUnderlyingObject(Obj);
        if (UO && UO != VAC.getValue() && SeenObjects.insert(UO).second) {
          const auto *OtherAA = A.getAAFor<AAUnderlyingObjects>(
              *this, IRPosition::value(*UO), DepClassTy::OPTIONAL);
          auto Pred = [&Values](Value &V) {
            Values.emplace_back(V, nullptr);
            return true;
          };

          if (!OtherAA || !OtherAA->forallUnderlyingObjects(Pred, Scope))
            llvm_unreachable(
                "The forall call should not return false at this position");

          continue;
        }

        if (isa<SelectInst>(Obj)) {
          Changed |= handleIndirect(A, *Obj, UnderlyingObjects, Scope);
          continue;
        }
        if (auto *PHI = dyn_cast<PHINode>(Obj)) {
          // Explicitly look through PHIs as we do not care about dynamically
          // uniqueness.
          for (unsigned u = 0, e = PHI->getNumIncomingValues(); u < e; u++) {
            Changed |= handleIndirect(A, *PHI->getIncomingValue(u),
                                      UnderlyingObjects, Scope);
          }
          continue;
        }

        Changed |= UnderlyingObjects.insert(Obj);
      }

      return Changed;
    };

    bool Changed = false;
    Changed |= DoUpdate(IntraAssumedUnderlyingObjects, AA::Intraprocedural);
    Changed |= DoUpdate(InterAssumedUnderlyingObjects, AA::Interprocedural);

    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  bool forallUnderlyingObjects(
      function_ref<bool(Value &)> Pred,
      AA::ValueScope Scope = AA::Interprocedural) const override {
    if (!isValidState())
      return Pred(getAssociatedValue());

    auto &AssumedUnderlyingObjects = Scope == AA::Intraprocedural
                                         ? IntraAssumedUnderlyingObjects
                                         : InterAssumedUnderlyingObjects;
    for (Value *Obj : AssumedUnderlyingObjects)
      if (!Pred(*Obj))
        return false;

    return true;
  }

private:
  /// Handle the case where the value is not the actual underlying value, such
  /// as a phi node or a select instruction.
  bool handleIndirect(Attributor &A, Value &V,
                      SmallSetVector<Value *, 8> &UnderlyingObjects,
                      AA::ValueScope Scope) {
    bool Changed = false;
    const auto *AA = A.getAAFor<AAUnderlyingObjects>(
        *this, IRPosition::value(V), DepClassTy::OPTIONAL);
    auto Pred = [&](Value &V) {
      Changed |= UnderlyingObjects.insert(&V);
      return true;
    };
    if (!AA || !AA->forallUnderlyingObjects(Pred, Scope))
      llvm_unreachable(
          "The forall call should not return false at this position");
    return Changed;
  }

  /// All the underlying objects collected so far via intra procedural scope.
  SmallSetVector<Value *, 8> IntraAssumedUnderlyingObjects;
  /// All the underlying objects collected so far via inter procedural scope.
  SmallSetVector<Value *, 8> InterAssumedUnderlyingObjects;
};

struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsFloating(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsArgument(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsCallSite(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsReturned(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};

struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {
  AAUnderlyingObjectsFunction(const IRPosition &IRP, Attributor &A)
      : AAUnderlyingObjectsImpl(IRP, A) {}
};
} // namespace

/// ------------------------ Address Space  ------------------------------------
namespace {
struct AAAddressSpaceImpl : public AAAddressSpace {
  AAAddressSpaceImpl(const IRPosition &IRP, Attributor &A)
      : AAAddressSpace(IRP, A) {}

  int32_t getAddressSpace() const override {
    assert(isValidState() && "the AA is invalid");
    return AssumedAddressSpace;
  }

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    assert(getAssociatedType()->isPtrOrPtrVectorTy() &&
           "Associated value is not a pointer");
  }

  ChangeStatus updateImpl(Attributor &A) override {
    int32_t OldAddressSpace = AssumedAddressSpace;
    auto *AUO = A.getOrCreateAAFor<AAUnderlyingObjects>(getIRPosition(), this,
                                                        DepClassTy::REQUIRED);
    auto Pred = [&](Value &Obj) {
      if (isa<UndefValue>(&Obj))
        return true;
      return takeAddressSpace(Obj.getType()->getPointerAddressSpace());
    };

    if (!AUO->forallUnderlyingObjects(Pred))
      return indicatePessimisticFixpoint();

    return OldAddressSpace == AssumedAddressSpace ? ChangeStatus::UNCHANGED
                                                  : ChangeStatus::CHANGED;
  }

  /// See AbstractAttribute::manifest(...).
  ChangeStatus manifest(Attributor &A) override {
    Value *AssociatedValue = &getAssociatedValue();
    Value *OriginalValue = peelAddrspacecast(AssociatedValue);
    if (getAddressSpace() == NoAddressSpace ||
        static_cast<uint32_t>(getAddressSpace()) ==
            getAssociatedType()->getPointerAddressSpace())
      return ChangeStatus::UNCHANGED;

    Type *NewPtrTy = PointerType::get(getAssociatedType()->getContext(),
                                      static_cast<uint32_t>(getAddressSpace()));
    bool UseOriginalValue =
        OriginalValue->getType()->getPointerAddressSpace() ==
        static_cast<uint32_t>(getAddressSpace());

    bool Changed = false;

    auto MakeChange = [&](Instruction *I, Use &U) {
      Changed = true;
      if (UseOriginalValue) {
        A.changeUseAfterManifest(U, *OriginalValue);
        return;
      }
      Instruction *CastInst = new AddrSpaceCastInst(OriginalValue, NewPtrTy);
      CastInst->insertBefore(cast<Instruction>(I));
      A.changeUseAfterManifest(U, *CastInst);
    };

    auto Pred = [&](const Use &U, bool &) {
      if (U.get() != AssociatedValue)
        return true;
      auto *Inst = dyn_cast<Instruction>(U.getUser());
      if (!Inst)
        return true;
      // This is a WA to make sure we only change uses from the corresponding
      // CGSCC if the AA is run on CGSCC instead of the entire module.
      if (!A.isRunOn(Inst->getFunction()))
        return true;
      if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
        MakeChange(Inst, const_cast<Use &>(U));
      return true;
    };

    // It doesn't matter if we can't check all uses as we can simply
    // conservatively ignore those that can not be visited.
    (void)A.checkForAllUses(Pred, *this, getAssociatedValue(),
                            /* CheckBBLivenessOnly */ true);

    return Changed ? ChangeStatus::CHANGED : ChangeStatus::UNCHANGED;
  }

  /// See AbstractAttribute::getAsStr().
  const std::string getAsStr(Attributor *A) const override {
    if (!isValidState())
      return "addrspace(<invalid>)";
    return "addrspace(" +
           (AssumedAddressSpace == NoAddressSpace
                ? "none"
                : std::to_string(AssumedAddressSpace)) +
           ")";
  }

private:
  int32_t AssumedAddressSpace = NoAddressSpace;

  bool takeAddressSpace(int32_t AS) {
    if (AssumedAddressSpace == NoAddressSpace) {
      AssumedAddressSpace = AS;
      return true;
    }
    return AssumedAddressSpace == AS;
  }

  static Value *peelAddrspacecast(Value *V) {
    if (auto *I = dyn_cast<AddrSpaceCastInst>(V))
      return peelAddrspacecast(I->getPointerOperand());
    if (auto *C = dyn_cast<ConstantExpr>(V))
      if (C->getOpcode() == Instruction::AddrSpaceCast)
        return peelAddrspacecast(C->getOperand(0));
    return V;
  }
};

struct AAAddressSpaceFloating final : AAAddressSpaceImpl {
  AAAddressSpaceFloating(const IRPosition &IRP, Attributor &A)
      : AAAddressSpaceImpl(IRP, A) {}

  void trackStatistics() const override {
    STATS_DECLTRACK_FLOATING_ATTR(addrspace);
  }
};

struct AAAddressSpaceReturned final : AAAddressSpaceImpl {
  AAAddressSpaceReturned(const IRPosition &IRP, Attributor &A)
      : AAAddressSpaceImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: we don't rewrite function argument for now because it will need to
    // rewrite the function signature and all call sites.
    (void)indicatePessimisticFixpoint();
  }

  void trackStatistics() const override {
    STATS_DECLTRACK_FNRET_ATTR(addrspace);
  }
};

struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {
  AAAddressSpaceCallSiteReturned(const IRPosition &IRP, Attributor &A)
      : AAAddressSpaceImpl(IRP, A) {}

  void trackStatistics() const override {
    STATS_DECLTRACK_CSRET_ATTR(addrspace);
  }
};

struct AAAddressSpaceArgument final : AAAddressSpaceImpl {
  AAAddressSpaceArgument(const IRPosition &IRP, Attributor &A)
      : AAAddressSpaceImpl(IRP, A) {}

  void trackStatistics() const override { STATS_DECLTRACK_ARG_ATTR(addrspace); }
};

struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {
  AAAddressSpaceCallSiteArgument(const IRPosition &IRP, Attributor &A)
      : AAAddressSpaceImpl(IRP, A) {}

  /// See AbstractAttribute::initialize(...).
  void initialize(Attributor &A) override {
    // TODO: we don't rewrite call site argument for now because it will need to
    // rewrite the function signature of the callee.
    (void)indicatePessimisticFixpoint();
  }

  void trackStatistics() const override {
    STATS_DECLTRACK_CSARG_ATTR(addrspace);
  }
};
} // namespace

const char AANoUnwind::ID = 0;
const char AANoSync::ID = 0;
const char AANoFree::ID = 0;
const char AANonNull::ID = 0;
const char AAMustProgress::ID = 0;
const char AANoRecurse::ID = 0;
const char AANonConvergent::ID = 0;
const char AAWillReturn::ID = 0;
const char AAUndefinedBehavior::ID = 0;
const char AANoAlias::ID = 0;
const char AAIntraFnReachability::ID = 0;
const char AANoReturn::ID = 0;
const char AAIsDead::ID = 0;
const char AADereferenceable::ID = 0;
const char AAAlign::ID = 0;
const char AAInstanceInfo::ID = 0;
const char AANoCapture::ID = 0;
const char AAValueSimplify::ID = 0;
const char AAHeapToStack::ID = 0;
const char AAPrivatizablePtr::ID = 0;
const char AAMemoryBehavior::ID = 0;
const char AAMemoryLocation::ID = 0;
const char AAValueConstantRange::ID = 0;
const char AAPotentialConstantValues::ID = 0;
const char AAPotentialValues::ID = 0;
const char AANoUndef::ID = 0;
const char AANoFPClass::ID = 0;
const char AACallEdges::ID = 0;
const char AAInterFnReachability::ID = 0;
const char AAPointerInfo::ID = 0;
const char AAAssumptionInfo::ID = 0;
const char AAUnderlyingObjects::ID = 0;
const char AAAddressSpace::ID = 0;

// Macro magic to create the static generator function for attributes that
// follow the naming scheme.

#define SWITCH_PK_INV(CLASS, PK, POS_NAME)                                     \
  case IRPosition::PK:                                                         \
    llvm_unreachable("Cannot create " #CLASS " for a " POS_NAME " position!");

#define SWITCH_PK_CREATE(CLASS, IRP, PK, SUFFIX)                               \
  case IRPosition::PK:                                                         \
    AA = new (A.Allocator) CLASS##SUFFIX(IRP, A);                              \
    ++NumAAs;                                                                  \
    break;

#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                 \
  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \
    CLASS *AA = nullptr;                                                       \
    switch (IRP.getPositionKind()) {                                           \
      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \
      SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \
      SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \
      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \
    }                                                                          \
    return *AA;                                                                \
  }

#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                    \
  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \
    CLASS *AA = nullptr;                                                       \
    switch (IRP.getPositionKind()) {                                           \
      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \
      SWITCH_PK_INV(CLASS, IRP_FUNCTION, "function")                           \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \
    }                                                                          \
    return *AA;                                                                \
  }

#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                      \
  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \
    CLASS *AA = nullptr;                                                       \
    switch (IRP.getPositionKind()) {                                           \
      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_RETURNED, Returned)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \
    }                                                                          \
    return *AA;                                                                \
  }

#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)            \
  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \
    CLASS *AA = nullptr;                                                       \
    switch (IRP.getPositionKind()) {                                           \
      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \
      SWITCH_PK_INV(CLASS, IRP_ARGUMENT, "argument")                           \
      SWITCH_PK_INV(CLASS, IRP_FLOAT, "floating")                              \
      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_RETURNED, "call site returned")       \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE_ARGUMENT, "call site argument")       \
      SWITCH_PK_INV(CLASS, IRP_CALL_SITE, "call site")                         \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \
    }                                                                          \
    return *AA;                                                                \
  }

#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(CLASS)                  \
  CLASS &CLASS::createForPosition(const IRPosition &IRP, Attributor &A) {      \
    CLASS *AA = nullptr;                                                       \
    switch (IRP.getPositionKind()) {                                           \
      SWITCH_PK_INV(CLASS, IRP_INVALID, "invalid")                             \
      SWITCH_PK_INV(CLASS, IRP_RETURNED, "returned")                           \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FUNCTION, Function)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE, CallSite)                    \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_FLOAT, Floating)                        \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_ARGUMENT, Argument)                     \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_RETURNED, CallSiteReturned)   \
      SWITCH_PK_CREATE(CLASS, IRP, IRP_CALL_SITE_ARGUMENT, CallSiteArgument)   \
    }                                                                          \
    return *AA;                                                                \
  }

CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUnwind)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoSync)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoRecurse)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAWillReturn)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoReturn)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryLocation)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AACallEdges)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAssumptionInfo)
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMustProgress)

CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPrivatizablePtr)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInstanceInfo)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueConstantRange)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialConstantValues)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPotentialValues)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoUndef)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFPClass)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAPointerInfo)
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAddressSpace)

CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAValueSimplify)
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIsDead)
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoFree)
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUnderlyingObjects)

CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAHeapToStack)
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAUndefinedBehavior)
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonConvergent)
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAIntraFnReachability)
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAInterFnReachability)

CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAMemoryBehavior)

#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef SWITCH_PK_CREATE
#undef SWITCH_PK_INV
