//===- Attributor.cpp - Module-wide attribute 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
//
//===----------------------------------------------------------------------===//
//
// This file implements an interprocedural pass that deduces and/or propagates
// attributes. This is done in an abstract interpretation style fixpoint
// iteration. 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/ArrayRef.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/InlineCost.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/MustExecute.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantFold.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/ModRef.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include <cstdint>
#include <memory>

#ifdef EXPENSIVE_CHECKS
#include "llvm/IR/Verifier.h"
#endif

#include <cassert>
#include <optional>
#include <string>

using namespace llvm;

#define DEBUG_TYPE "attributor"
#define VERBOSE_DEBUG_TYPE DEBUG_TYPE "-verbose"

DEBUG_COUNTER(ManifestDBGCounter, "attributor-manifest",
              "Determine what attributes are manifested in the IR");

STATISTIC(NumFnDeleted, "Number of function deleted");
STATISTIC(NumFnWithExactDefinition,
          "Number of functions with exact definitions");
STATISTIC(NumFnWithoutExactDefinition,
          "Number of functions without exact definitions");
STATISTIC(NumFnShallowWrappersCreated, "Number of shallow wrappers created");
STATISTIC(NumAttributesTimedOut,
          "Number of abstract attributes timed out before fixpoint");
STATISTIC(NumAttributesValidFixpoint,
          "Number of abstract attributes in a valid fixpoint state");
STATISTIC(NumAttributesManifested,
          "Number of abstract attributes manifested in IR");

// TODO: Determine a good default value.
//
// In the LLVM-TS and SPEC2006, 32 seems to not induce compile time overheads
// (when run with the first 5 abstract attributes). The results also indicate
// that we never reach 32 iterations but always find a fixpoint sooner.
//
// This will become more evolved once we perform two interleaved fixpoint
// iterations: bottom-up and top-down.
static cl::opt<unsigned>
    SetFixpointIterations("attributor-max-iterations", cl::Hidden,
                          cl::desc("Maximal number of fixpoint iterations."),
                          cl::init(32));

static cl::opt<unsigned>
    MaxSpecializationPerCB("attributor-max-specializations-per-call-base",
                           cl::Hidden,
                           cl::desc("Maximal number of callees specialized for "
                                    "a call base"),
                           cl::init(UINT32_MAX));

static cl::opt<unsigned, true> MaxInitializationChainLengthX(
    "attributor-max-initialization-chain-length", cl::Hidden,
    cl::desc(
        "Maximal number of chained initializations (to avoid stack overflows)"),
    cl::location(MaxInitializationChainLength), cl::init(1024));
unsigned llvm::MaxInitializationChainLength;

static cl::opt<bool> AnnotateDeclarationCallSites(
    "attributor-annotate-decl-cs", cl::Hidden,
    cl::desc("Annotate call sites of function declarations."), cl::init(false));

static cl::opt<bool> EnableHeapToStack("enable-heap-to-stack-conversion",
                                       cl::init(true), cl::Hidden);

static cl::opt<bool>
    AllowShallowWrappers("attributor-allow-shallow-wrappers", cl::Hidden,
                         cl::desc("Allow the Attributor to create shallow "
                                  "wrappers for non-exact definitions."),
                         cl::init(false));

static cl::opt<bool>
    AllowDeepWrapper("attributor-allow-deep-wrappers", cl::Hidden,
                     cl::desc("Allow the Attributor to use IP information "
                              "derived from non-exact functions via cloning"),
                     cl::init(false));

// These options can only used for debug builds.
#ifndef NDEBUG
static cl::list<std::string>
    SeedAllowList("attributor-seed-allow-list", cl::Hidden,
                  cl::desc("Comma separated list of attribute names that are "
                           "allowed to be seeded."),
                  cl::CommaSeparated);

static cl::list<std::string> FunctionSeedAllowList(
    "attributor-function-seed-allow-list", cl::Hidden,
    cl::desc("Comma separated list of function names that are "
             "allowed to be seeded."),
    cl::CommaSeparated);
#endif

static cl::opt<bool>
    DumpDepGraph("attributor-dump-dep-graph", cl::Hidden,
                 cl::desc("Dump the dependency graph to dot files."),
                 cl::init(false));

static cl::opt<std::string> DepGraphDotFileNamePrefix(
    "attributor-depgraph-dot-filename-prefix", cl::Hidden,
    cl::desc("The prefix used for the CallGraph dot file names."));

static cl::opt<bool> ViewDepGraph("attributor-view-dep-graph", cl::Hidden,
                                  cl::desc("View the dependency graph."),
                                  cl::init(false));

static cl::opt<bool> PrintDependencies("attributor-print-dep", cl::Hidden,
                                       cl::desc("Print attribute dependencies"),
                                       cl::init(false));

static cl::opt<bool> EnableCallSiteSpecific(
    "attributor-enable-call-site-specific-deduction", cl::Hidden,
    cl::desc("Allow the Attributor to do call site specific analysis"),
    cl::init(false));

static cl::opt<bool>
    PrintCallGraph("attributor-print-call-graph", cl::Hidden,
                   cl::desc("Print Attributor's internal call graph"),
                   cl::init(false));

static cl::opt<bool> SimplifyAllLoads("attributor-simplify-all-loads",
                                      cl::Hidden,
                                      cl::desc("Try to simplify all loads."),
                                      cl::init(true));

static cl::opt<bool> CloseWorldAssumption(
    "attributor-assume-closed-world", cl::Hidden,
    cl::desc("Should a closed world be assumed, or not. Default if not set."));

/// Logic operators for the change status enum class.
///
///{
ChangeStatus llvm::operator|(ChangeStatus L, ChangeStatus R) {
  return L == ChangeStatus::CHANGED ? L : R;
}
ChangeStatus &llvm::operator|=(ChangeStatus &L, ChangeStatus R) {
  L = L | R;
  return L;
}
ChangeStatus llvm::operator&(ChangeStatus L, ChangeStatus R) {
  return L == ChangeStatus::UNCHANGED ? L : R;
}
ChangeStatus &llvm::operator&=(ChangeStatus &L, ChangeStatus R) {
  L = L & R;
  return L;
}
///}

namespace {
/// NVPTX/AMDGPU address space values (shared between both targets)
enum class NVPTXAMDGPUAddressSpace : unsigned {
  Generic = 0,
  Global = 1,
  Shared = 3,
  Constant = 4,
  Local = 5,
};

/// SPIRV address space values (StorageClass)
enum class SPIRVAddressSpace : unsigned {
  Local = 0,    // Function (private/local)
  Global = 1,   // CrossWorkgroup (global)
  Constant = 2, // UniformConstant (constant)
  Shared = 3,   // Workgroup (shared)
  Generic = 4,  // Generic
};
} // namespace

bool AA::isGPU(const Module &M) {
  Triple T(M.getTargetTriple());
  return T.isGPU();
}

bool AA::isGPUGenericAddressSpace(const Module &M, unsigned AS) {
  assert(AA::isGPU(M) && "Only callable on GPU targets");
  Triple T(M.getTargetTriple());

  if (T.isSPIRV())
    return AS == static_cast<unsigned>(SPIRVAddressSpace::Generic);

  return AS == static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Generic);
}

bool AA::isGPUGlobalAddressSpace(const Module &M, unsigned AS) {
  assert(AA::isGPU(M) && "Only callable on GPU targets");
  Triple T(M.getTargetTriple());

  if (T.isSPIRV())
    return AS == static_cast<unsigned>(SPIRVAddressSpace::Global);

  return AS == static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Global);
}

bool AA::isGPUSharedAddressSpace(const Module &M, unsigned AS) {
  assert(AA::isGPU(M) && "Only callable on GPU targets");
  Triple T(M.getTargetTriple());

  if (T.isSPIRV())
    return AS == static_cast<unsigned>(SPIRVAddressSpace::Shared);

  return AS == static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Shared);
}

bool AA::isGPUConstantAddressSpace(const Module &M, unsigned AS) {
  assert(AA::isGPU(M) && "Only callable on GPU targets");
  Triple T(M.getTargetTriple());

  if (T.isSPIRV())
    return AS == static_cast<unsigned>(SPIRVAddressSpace::Constant);

  return AS == static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Constant);
}

bool AA::isGPULocalAddressSpace(const Module &M, unsigned AS) {
  assert(AA::isGPU(M) && "Only callable on GPU targets");
  Triple T(M.getTargetTriple());

  if (T.isSPIRV())
    return AS == static_cast<unsigned>(SPIRVAddressSpace::Local);

  return AS == static_cast<unsigned>(NVPTXAMDGPUAddressSpace::Local);
}

bool AA::isNoSyncInst(Attributor &A, const Instruction &I,
                      const AbstractAttribute &QueryingAA) {
  // We are looking for volatile instructions or non-relaxed atomics.
  if (const auto *CB = dyn_cast<CallBase>(&I)) {
    if (CB->hasFnAttr(Attribute::NoSync))
      return true;

    // Non-convergent and readnone imply nosync.
    if (!CB->isConvergent() && !CB->mayReadOrWriteMemory())
      return true;

    bool IsKnownNoSync;
    return AA::hasAssumedIRAttr<Attribute::NoSync>(
        A, &QueryingAA, IRPosition::callsite_function(*CB),
        DepClassTy::OPTIONAL, IsKnownNoSync);
  }

  if (!I.mayReadOrWriteMemory())
    return true;

  return !AANoSync::isNonRelaxedAtomic(&I);
}

bool AA::isDynamicallyUnique(Attributor &A, const AbstractAttribute &QueryingAA,
                             const Value &V, bool ForAnalysisOnly) {
  // TODO: See the AAInstanceInfo class comment.
  if (!ForAnalysisOnly)
    return false;
  auto *InstanceInfoAA = A.getAAFor<AAInstanceInfo>(
      QueryingAA, IRPosition::value(V), DepClassTy::OPTIONAL);
  return InstanceInfoAA && InstanceInfoAA->isAssumedUniqueForAnalysis();
}

Constant *
AA::getInitialValueForObj(Attributor &A, const AbstractAttribute &QueryingAA,
                          Value &Obj, Type &Ty, const TargetLibraryInfo *TLI,
                          const DataLayout &DL, AA::RangeTy *RangePtr) {
  if (Constant *Init = getInitialValueOfAllocation(&Obj, TLI, &Ty))
    return Init;
  auto *GV = dyn_cast<GlobalVariable>(&Obj);
  if (!GV)
    return nullptr;

  bool UsedAssumedInformation = false;
  Constant *Initializer = nullptr;
  if (A.hasGlobalVariableSimplificationCallback(*GV)) {
    auto AssumedGV = A.getAssumedInitializerFromCallBack(
        *GV, &QueryingAA, UsedAssumedInformation);
    Initializer = *AssumedGV;
    if (!Initializer)
      return nullptr;
  } else {
    if (!GV->hasLocalLinkage()) {
      // Externally visible global that's either non-constant,
      // or a constant with an uncertain initializer.
      if (!GV->hasDefinitiveInitializer() || !GV->isConstant())
        return nullptr;
    }

    // Globals with local linkage are always initialized.
    assert(!GV->hasLocalLinkage() || GV->hasInitializer());

    if (!Initializer)
      Initializer = GV->getInitializer();
  }

  if (RangePtr && !RangePtr->offsetOrSizeAreUnknown()) {
    int64_t StorageSize = DL.getTypeStoreSize(&Ty);
    if (StorageSize != RangePtr->Size)
      return nullptr;
    APInt Offset = APInt(64, RangePtr->Offset);
    return ConstantFoldLoadFromConst(Initializer, &Ty, Offset, DL);
  }

  return ConstantFoldLoadFromUniformValue(Initializer, &Ty, DL);
}

bool AA::isValidInScope(const Value &V, const Function *Scope) {
  if (isa<Constant>(V))
    return true;
  if (auto *I = dyn_cast<Instruction>(&V))
    return I->getFunction() == Scope;
  if (auto *A = dyn_cast<Argument>(&V))
    return A->getParent() == Scope;
  return false;
}

bool AA::isValidAtPosition(const AA::ValueAndContext &VAC,
                           InformationCache &InfoCache) {
  if (isa<Constant>(VAC.getValue()) || VAC.getValue() == VAC.getCtxI())
    return true;
  const Function *Scope = nullptr;
  const Instruction *CtxI = VAC.getCtxI();
  if (CtxI)
    Scope = CtxI->getFunction();
  if (auto *A = dyn_cast<Argument>(VAC.getValue()))
    return A->getParent() == Scope;
  if (auto *I = dyn_cast<Instruction>(VAC.getValue())) {
    if (I->getFunction() == Scope) {
      if (const DominatorTree *DT =
              InfoCache.getAnalysisResultForFunction<DominatorTreeAnalysis>(
                  *Scope))
        return DT->dominates(I, CtxI);
      // Local dominance check mostly for the old PM passes.
      if (CtxI && I->getParent() == CtxI->getParent())
        return llvm::any_of(
            make_range(I->getIterator(), I->getParent()->end()),
            [&](const Instruction &AfterI) { return &AfterI == CtxI; });
    }
  }
  return false;
}

Value *AA::getWithType(Value &V, Type &Ty) {
  if (V.getType() == &Ty)
    return &V;
  if (isa<PoisonValue>(V))
    return PoisonValue::get(&Ty);
  if (isa<UndefValue>(V))
    return UndefValue::get(&Ty);
  if (auto *C = dyn_cast<Constant>(&V)) {
    if (C->isNullValue() && !Ty.isPtrOrPtrVectorTy())
      return Constant::getNullValue(&Ty);
    if (C->getType()->isPointerTy() && Ty.isPointerTy())
      return ConstantExpr::getPointerCast(C, &Ty);
    if (C->getType()->getPrimitiveSizeInBits() >= Ty.getPrimitiveSizeInBits()) {
      if (C->getType()->isIntegerTy() && Ty.isIntegerTy())
        return ConstantExpr::getTrunc(C, &Ty, /* OnlyIfReduced */ true);
      if (C->getType()->isFloatingPointTy() && Ty.isFloatingPointTy())
        return ConstantFoldCastInstruction(Instruction::FPTrunc, C, &Ty);
    }
  }
  return nullptr;
}

std::optional<Value *>
AA::combineOptionalValuesInAAValueLatice(const std::optional<Value *> &A,
                                         const std::optional<Value *> &B,
                                         Type *Ty) {
  if (A == B)
    return A;
  if (!B)
    return A;
  if (*B == nullptr)
    return nullptr;
  if (!A)
    return Ty ? getWithType(**B, *Ty) : nullptr;
  if (*A == nullptr)
    return nullptr;
  if (!Ty)
    Ty = (*A)->getType();
  if (isa_and_nonnull<UndefValue>(*A))
    return getWithType(**B, *Ty);
  if (isa<UndefValue>(*B))
    return A;
  if (*A && *B && *A == getWithType(**B, *Ty))
    return A;
  return nullptr;
}

template <bool IsLoad, typename Ty>
static bool getPotentialCopiesOfMemoryValue(
    Attributor &A, Ty &I, SmallSetVector<Value *, 4> &PotentialCopies,
    SmallSetVector<Instruction *, 4> *PotentialValueOrigins,
    const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
    bool OnlyExact) {
  LLVM_DEBUG(dbgs() << "Trying to determine the potential copies of " << I
                    << " (only exact: " << OnlyExact << ")\n";);

  Value &Ptr = *I.getPointerOperand();
  // Containers to remember the pointer infos and new copies while we are not
  // sure that we can find all of them. If we abort we want to avoid spurious
  // dependences and potential copies in the provided container.
  SmallVector<const AAPointerInfo *> PIs;
  SmallSetVector<Value *, 8> NewCopies;
  SmallSetVector<Instruction *, 8> NewCopyOrigins;

  const auto *TLI =
      A.getInfoCache().getTargetLibraryInfoForFunction(*I.getFunction());

  auto Pred = [&](Value &Obj) {
    LLVM_DEBUG(dbgs() << "Visit underlying object " << Obj << "\n");
    if (isa<UndefValue>(&Obj))
      return true;
    if (isa<ConstantPointerNull>(&Obj)) {
      // A null pointer access can be undefined but any offset from null may
      // be OK. We do not try to optimize the latter.
      if (!NullPointerIsDefined(I.getFunction(),
                                Ptr.getType()->getPointerAddressSpace()) &&
          A.getAssumedSimplified(Ptr, QueryingAA, UsedAssumedInformation,
                                 AA::Interprocedural) == &Obj)
        return true;
      LLVM_DEBUG(
          dbgs() << "Underlying object is a valid nullptr, giving up.\n";);
      return false;
    }
    // TODO: Use assumed noalias return.
    if (!isa<AllocaInst>(&Obj) && !isa<GlobalVariable>(&Obj) &&
        !(IsLoad ? isAllocationFn(&Obj, TLI) : isNoAliasCall(&Obj))) {
      LLVM_DEBUG(dbgs() << "Underlying object is not supported yet: " << Obj
                        << "\n";);
      return false;
    }
    if (auto *GV = dyn_cast<GlobalVariable>(&Obj))
      if (!GV->hasLocalLinkage() &&
          !(GV->isConstant() && GV->hasInitializer())) {
        LLVM_DEBUG(dbgs() << "Underlying object is global with external "
                             "linkage, not supported yet: "
                          << Obj << "\n";);
        return false;
      }

    bool NullOnly = true;
    bool NullRequired = false;
    auto CheckForNullOnlyAndUndef = [&](std::optional<Value *> V,
                                        bool IsExact) {
      if (!V || *V == nullptr)
        NullOnly = false;
      else if (isa<UndefValue>(*V))
        /* No op */;
      else if (isa<Constant>(*V) && cast<Constant>(*V)->isNullValue())
        NullRequired = !IsExact;
      else
        NullOnly = false;
    };

    auto AdjustWrittenValueType = [&](const AAPointerInfo::Access &Acc,
                                      Value &V) {
      Value *AdjV = AA::getWithType(V, *I.getType());
      if (!AdjV) {
        LLVM_DEBUG(dbgs() << "Underlying object written but stored value "
                             "cannot be converted to read type: "
                          << *Acc.getRemoteInst() << " : " << *I.getType()
                          << "\n";);
      }
      return AdjV;
    };

    auto SkipCB = [&](const AAPointerInfo::Access &Acc) {
      if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead()))
        return true;
      if (IsLoad) {
        if (Acc.isWrittenValueYetUndetermined())
          return true;
        if (PotentialValueOrigins && !isa<AssumeInst>(Acc.getRemoteInst()))
          return false;
        if (!Acc.isWrittenValueUnknown())
          if (Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue()))
            if (NewCopies.count(V)) {
              NewCopyOrigins.insert(Acc.getRemoteInst());
              return true;
            }
        if (auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst()))
          if (Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand()))
            if (NewCopies.count(V)) {
              NewCopyOrigins.insert(Acc.getRemoteInst());
              return true;
            }
      }
      return false;
    };

    auto CheckAccess = [&](const AAPointerInfo::Access &Acc, bool IsExact) {
      if ((IsLoad && !Acc.isWriteOrAssumption()) || (!IsLoad && !Acc.isRead()))
        return true;
      if (IsLoad && Acc.isWrittenValueYetUndetermined())
        return true;
      CheckForNullOnlyAndUndef(Acc.getContent(), IsExact);
      if (OnlyExact && !IsExact && !NullOnly &&
          !isa_and_nonnull<UndefValue>(Acc.getWrittenValue())) {
        LLVM_DEBUG(dbgs() << "Non exact access " << *Acc.getRemoteInst()
                          << ", abort!\n");
        return false;
      }
      if (NullRequired && !NullOnly) {
        LLVM_DEBUG(dbgs() << "Required all `null` accesses due to non exact "
                             "one, however found non-null one: "
                          << *Acc.getRemoteInst() << ", abort!\n");
        return false;
      }
      if (IsLoad) {
        assert(isa<LoadInst>(I) && "Expected load or store instruction only!");
        if (!Acc.isWrittenValueUnknown()) {
          Value *V = AdjustWrittenValueType(Acc, *Acc.getWrittenValue());
          if (!V)
            return false;
          NewCopies.insert(V);
          if (PotentialValueOrigins)
            NewCopyOrigins.insert(Acc.getRemoteInst());
          return true;
        }
        auto *SI = dyn_cast<StoreInst>(Acc.getRemoteInst());
        if (!SI) {
          LLVM_DEBUG(dbgs() << "Underlying object written through a non-store "
                               "instruction not supported yet: "
                            << *Acc.getRemoteInst() << "\n";);
          return false;
        }
        Value *V = AdjustWrittenValueType(Acc, *SI->getValueOperand());
        if (!V)
          return false;
        NewCopies.insert(V);
        if (PotentialValueOrigins)
          NewCopyOrigins.insert(SI);
      } else {
        assert(isa<StoreInst>(I) && "Expected load or store instruction only!");
        auto *LI = dyn_cast<LoadInst>(Acc.getRemoteInst());
        if (!LI && OnlyExact) {
          LLVM_DEBUG(dbgs() << "Underlying object read through a non-load "
                               "instruction not supported yet: "
                            << *Acc.getRemoteInst() << "\n";);
          return false;
        }
        NewCopies.insert(Acc.getRemoteInst());
      }
      return true;
    };

    // If the value has been written to we don't need the initial value of the
    // object.
    bool HasBeenWrittenTo = false;

    AA::RangeTy Range;
    auto *PI = A.getAAFor<AAPointerInfo>(QueryingAA, IRPosition::value(Obj),
                                         DepClassTy::NONE);
    if (!PI || !PI->forallInterferingAccesses(
                   A, QueryingAA, I,
                   /* FindInterferingWrites */ IsLoad,
                   /* FindInterferingReads */ !IsLoad, CheckAccess,
                   HasBeenWrittenTo, Range, SkipCB)) {
      LLVM_DEBUG(
          dbgs()
          << "Failed to verify all interfering accesses for underlying object: "
          << Obj << "\n");
      return false;
    }

    if (IsLoad && !HasBeenWrittenTo && !Range.isUnassigned()) {
      const DataLayout &DL = A.getDataLayout();
      Value *InitialValue = AA::getInitialValueForObj(
          A, QueryingAA, Obj, *I.getType(), TLI, DL, &Range);
      if (!InitialValue) {
        LLVM_DEBUG(dbgs() << "Could not determine required initial value of "
                             "underlying object, abort!\n");
        return false;
      }
      CheckForNullOnlyAndUndef(InitialValue, /* IsExact */ true);
      if (NullRequired && !NullOnly) {
        LLVM_DEBUG(dbgs() << "Non exact access but initial value that is not "
                             "null or undef, abort!\n");
        return false;
      }

      NewCopies.insert(InitialValue);
      if (PotentialValueOrigins)
        NewCopyOrigins.insert(nullptr);
    }

    PIs.push_back(PI);

    return true;
  };

  const auto *AAUO = A.getAAFor<AAUnderlyingObjects>(
      QueryingAA, IRPosition::value(Ptr), DepClassTy::OPTIONAL);
  if (!AAUO || !AAUO->forallUnderlyingObjects(Pred)) {
    LLVM_DEBUG(
        dbgs() << "Underlying objects stored into could not be determined\n";);
    return false;
  }

  // Only if we were successful collection all potential copies we record
  // dependences (on non-fix AAPointerInfo AAs). We also only then modify the
  // given PotentialCopies container.
  for (const auto *PI : PIs) {
    if (!PI->getState().isAtFixpoint())
      UsedAssumedInformation = true;
    A.recordDependence(*PI, QueryingAA, DepClassTy::OPTIONAL);
  }
  PotentialCopies.insert_range(NewCopies);
  if (PotentialValueOrigins)
    PotentialValueOrigins->insert_range(NewCopyOrigins);

  return true;
}

bool AA::getPotentiallyLoadedValues(
    Attributor &A, LoadInst &LI, SmallSetVector<Value *, 4> &PotentialValues,
    SmallSetVector<Instruction *, 4> &PotentialValueOrigins,
    const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
    bool OnlyExact) {
  return getPotentialCopiesOfMemoryValue</* IsLoad */ true>(
      A, LI, PotentialValues, &PotentialValueOrigins, QueryingAA,
      UsedAssumedInformation, OnlyExact);
}

bool AA::getPotentialCopiesOfStoredValue(
    Attributor &A, StoreInst &SI, SmallSetVector<Value *, 4> &PotentialCopies,
    const AbstractAttribute &QueryingAA, bool &UsedAssumedInformation,
    bool OnlyExact) {
  return getPotentialCopiesOfMemoryValue</* IsLoad */ false>(
      A, SI, PotentialCopies, nullptr, QueryingAA, UsedAssumedInformation,
      OnlyExact);
}

static bool isAssumedReadOnlyOrReadNone(Attributor &A, const IRPosition &IRP,
                                        const AbstractAttribute &QueryingAA,
                                        bool RequireReadNone, bool &IsKnown) {
  if (RequireReadNone) {
    if (AA::hasAssumedIRAttr<Attribute::ReadNone>(
            A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
            /* IgnoreSubsumingPositions */ true))
      return true;
  } else if (AA::hasAssumedIRAttr<Attribute::ReadOnly>(
                 A, &QueryingAA, IRP, DepClassTy::OPTIONAL, IsKnown,
                 /* IgnoreSubsumingPositions */ true))
    return true;

  IRPosition::Kind Kind = IRP.getPositionKind();
  if (Kind == IRPosition::IRP_FUNCTION || Kind == IRPosition::IRP_CALL_SITE) {
    const auto *MemLocAA =
        A.getAAFor<AAMemoryLocation>(QueryingAA, IRP, DepClassTy::NONE);
    if (MemLocAA && MemLocAA->isAssumedReadNone()) {
      IsKnown = MemLocAA->isKnownReadNone();
      if (!IsKnown)
        A.recordDependence(*MemLocAA, QueryingAA, DepClassTy::OPTIONAL);
      return true;
    }
  }

  const auto *MemBehaviorAA =
      A.getAAFor<AAMemoryBehavior>(QueryingAA, IRP, DepClassTy::NONE);
  if (MemBehaviorAA &&
      (MemBehaviorAA->isAssumedReadNone() ||
       (!RequireReadNone && MemBehaviorAA->isAssumedReadOnly()))) {
    IsKnown = RequireReadNone ? MemBehaviorAA->isKnownReadNone()
                              : MemBehaviorAA->isKnownReadOnly();
    if (!IsKnown)
      A.recordDependence(*MemBehaviorAA, QueryingAA, DepClassTy::OPTIONAL);
    return true;
  }

  return false;
}

bool AA::isAssumedReadOnly(Attributor &A, const IRPosition &IRP,
                           const AbstractAttribute &QueryingAA, bool &IsKnown) {
  return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
                                     /* RequireReadNone */ false, IsKnown);
}
bool AA::isAssumedReadNone(Attributor &A, const IRPosition &IRP,
                           const AbstractAttribute &QueryingAA, bool &IsKnown) {
  return isAssumedReadOnlyOrReadNone(A, IRP, QueryingAA,
                                     /* RequireReadNone */ true, IsKnown);
}

static bool
isPotentiallyReachable(Attributor &A, const Instruction &FromI,
                       const Instruction *ToI, const Function &ToFn,
                       const AbstractAttribute &QueryingAA,
                       const AA::InstExclusionSetTy *ExclusionSet,
                       std::function<bool(const Function &F)> GoBackwardsCB) {
  DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {
    dbgs() << "[AA] isPotentiallyReachable @" << ToFn.getName() << " from "
           << FromI << " [GBCB: " << bool(GoBackwardsCB) << "][#ExS: "
           << (ExclusionSet ? std::to_string(ExclusionSet->size()) : "none")
           << "]\n";
    if (ExclusionSet)
      for (auto *ES : *ExclusionSet)
        dbgs() << *ES << "\n";
  });

  // We know kernels (generally) cannot be called from within the module. Thus,
  // for reachability we would need to step back from a kernel which would allow
  // us to reach anything anyway. Even if a kernel is invoked from another
  // kernel, values like allocas and shared memory are not accessible. We
  // implicitly check for this situation to avoid costly lookups.
  if (GoBackwardsCB && &ToFn != FromI.getFunction() &&
      !GoBackwardsCB(*FromI.getFunction()) && A.getInfoCache().isKernel(ToFn) &&
      A.getInfoCache().isKernel(*FromI.getFunction())) {
    LLVM_DEBUG(dbgs() << "[AA] assume kernel cannot be reached from within the "
                         "module; success\n";);
    return false;
  }

  // If we can go arbitrarily backwards we will eventually reach an entry point
  // that can reach ToI. Only if a set of blocks through which we cannot go is
  // provided, or once we track internal functions not accessible from the
  // outside, it makes sense to perform backwards analysis in the absence of a
  // GoBackwardsCB.
  if (!GoBackwardsCB && !ExclusionSet) {
    LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromI
                      << " is not checked backwards and does not have an "
                         "exclusion set, abort\n");
    return true;
  }

  SmallPtrSet<const Instruction *, 8> Visited;
  SmallVector<const Instruction *> Worklist;
  Worklist.push_back(&FromI);

  while (!Worklist.empty()) {
    const Instruction *CurFromI = Worklist.pop_back_val();
    if (!Visited.insert(CurFromI).second)
      continue;

    const Function *FromFn = CurFromI->getFunction();
    if (FromFn == &ToFn) {
      if (!ToI)
        return true;
      LLVM_DEBUG(dbgs() << "[AA] check " << *ToI << " from " << *CurFromI
                        << " intraprocedurally\n");
      const auto *ReachabilityAA = A.getAAFor<AAIntraFnReachability>(
          QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL);
      bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
                                           A, *CurFromI, *ToI, ExclusionSet);
      LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " "
                        << (Result ? "can potentially " : "cannot ") << "reach "
                        << *ToI << " [Intra]\n");
      if (Result)
        return true;
    }

    bool Result = true;
    if (!ToFn.isDeclaration() && ToI) {
      const auto *ToReachabilityAA = A.getAAFor<AAIntraFnReachability>(
          QueryingAA, IRPosition::function(ToFn), DepClassTy::OPTIONAL);
      const Instruction &EntryI = ToFn.getEntryBlock().front();
      Result = !ToReachabilityAA || ToReachabilityAA->isAssumedReachable(
                                        A, EntryI, *ToI, ExclusionSet);
      LLVM_DEBUG(dbgs() << "[AA] Entry " << EntryI << " of @" << ToFn.getName()
                        << " " << (Result ? "can potentially " : "cannot ")
                        << "reach @" << *ToI << " [ToFn]\n");
    }

    if (Result) {
      // The entry of the ToFn can reach the instruction ToI. If the current
      // instruction is already known to reach the ToFn.
      const auto *FnReachabilityAA = A.getAAFor<AAInterFnReachability>(
          QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL);
      Result = !FnReachabilityAA || FnReachabilityAA->instructionCanReach(
                                        A, *CurFromI, ToFn, ExclusionSet);
      LLVM_DEBUG(dbgs() << "[AA] " << *CurFromI << " in @" << FromFn->getName()
                        << " " << (Result ? "can potentially " : "cannot ")
                        << "reach @" << ToFn.getName() << " [FromFn]\n");
      if (Result)
        return true;
    }

    // TODO: Check assumed nounwind.
    const auto *ReachabilityAA = A.getAAFor<AAIntraFnReachability>(
        QueryingAA, IRPosition::function(*FromFn), DepClassTy::OPTIONAL);
    auto ReturnInstCB = [&](Instruction &Ret) {
      bool Result = !ReachabilityAA || ReachabilityAA->isAssumedReachable(
                                           A, *CurFromI, Ret, ExclusionSet);
      LLVM_DEBUG(dbgs() << "[AA][Ret] " << *CurFromI << " "
                        << (Result ? "can potentially " : "cannot ") << "reach "
                        << Ret << " [Intra]\n");
      return !Result;
    };

    // Check if we can reach returns.
    bool UsedAssumedInformation = false;
    if (A.checkForAllInstructions(ReturnInstCB, FromFn, &QueryingAA,
                                  {Instruction::Ret}, UsedAssumedInformation)) {
      LLVM_DEBUG(dbgs() << "[AA] No return is reachable, done\n");
      continue;
    }

    if (!GoBackwardsCB) {
      LLVM_DEBUG(dbgs() << "[AA] check @" << ToFn.getName() << " from " << FromI
                        << " is not checked backwards, abort\n");
      return true;
    }

    // If we do not go backwards from the FromFn we are done here and so far we
    // could not find a way to reach ToFn/ToI.
    if (!GoBackwardsCB(*FromFn))
      continue;

    LLVM_DEBUG(dbgs() << "Stepping backwards to the call sites of @"
                      << FromFn->getName() << "\n");

    auto CheckCallSite = [&](AbstractCallSite ACS) {
      CallBase *CB = ACS.getInstruction();
      if (!CB)
        return false;

      if (isa<InvokeInst>(CB))
        return false;

      Instruction *Inst = CB->getNextNode();
      Worklist.push_back(Inst);
      return true;
    };

    Result = !A.checkForAllCallSites(CheckCallSite, *FromFn,
                                     /* RequireAllCallSites */ true,
                                     &QueryingAA, UsedAssumedInformation);
    if (Result) {
      LLVM_DEBUG(dbgs() << "[AA] stepping back to call sites from " << *CurFromI
                        << " in @" << FromFn->getName()
                        << " failed, give up\n");
      return true;
    }

    LLVM_DEBUG(dbgs() << "[AA] stepped back to call sites from " << *CurFromI
                      << " in @" << FromFn->getName()
                      << " worklist size is: " << Worklist.size() << "\n");
  }
  return false;
}

bool AA::isPotentiallyReachable(
    Attributor &A, const Instruction &FromI, const Instruction &ToI,
    const AbstractAttribute &QueryingAA,
    const AA::InstExclusionSetTy *ExclusionSet,
    std::function<bool(const Function &F)> GoBackwardsCB) {
  const Function *ToFn = ToI.getFunction();
  return ::isPotentiallyReachable(A, FromI, &ToI, *ToFn, QueryingAA,
                                  ExclusionSet, GoBackwardsCB);
}

bool AA::isPotentiallyReachable(
    Attributor &A, const Instruction &FromI, const Function &ToFn,
    const AbstractAttribute &QueryingAA,
    const AA::InstExclusionSetTy *ExclusionSet,
    std::function<bool(const Function &F)> GoBackwardsCB) {
  return ::isPotentiallyReachable(A, FromI, /* ToI */ nullptr, ToFn, QueryingAA,
                                  ExclusionSet, GoBackwardsCB);
}

bool AA::isAssumedThreadLocalObject(Attributor &A, Value &Obj,
                                    const AbstractAttribute &QueryingAA) {
  if (isa<UndefValue>(Obj))
    return true;
  if (isa<AllocaInst>(Obj)) {
    InformationCache &InfoCache = A.getInfoCache();
    if (!InfoCache.stackIsAccessibleByOtherThreads()) {
      LLVM_DEBUG(
          dbgs() << "[AA] Object '" << Obj
                 << "' is thread local; stack objects are thread local.\n");
      return true;
    }
    bool IsKnownNoCapture;
    bool IsAssumedNoCapture = AA::hasAssumedIRAttr<Attribute::Captures>(
        A, &QueryingAA, IRPosition::value(Obj), DepClassTy::OPTIONAL,
        IsKnownNoCapture);
    LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is "
                      << (IsAssumedNoCapture ? "" : "not") << " thread local; "
                      << (IsAssumedNoCapture ? "non-" : "")
                      << "captured stack object.\n");
    return IsAssumedNoCapture;
  }
  if (auto *GV = dyn_cast<GlobalVariable>(&Obj)) {
    if (GV->isConstant()) {
      LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj
                        << "' is thread local; constant global\n");
      return true;
    }
    if (GV->isThreadLocal()) {
      LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj
                        << "' is thread local; thread local global\n");
      return true;
    }
  }

  if (A.getInfoCache().IsTargetGPU()) {
    if (AA::isGPULocalAddressSpace(A.getInfoCache().getModule(),
                                   Obj.getType()->getPointerAddressSpace())) {
      LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj
                        << "' is thread local; GPU local memory\n");
      return true;
    }
    if (AA::isGPUConstantAddressSpace(
            A.getInfoCache().getModule(),
            Obj.getType()->getPointerAddressSpace())) {
      LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj
                        << "' is thread local; GPU constant memory\n");
      return true;
    }
  }

  LLVM_DEBUG(dbgs() << "[AA] Object '" << Obj << "' is not thread local\n");
  return false;
}

bool AA::isPotentiallyAffectedByBarrier(Attributor &A, const Instruction &I,
                                        const AbstractAttribute &QueryingAA) {
  if (!I.mayHaveSideEffects() && !I.mayReadFromMemory())
    return false;

  SmallSetVector<const Value *, 8> Ptrs;

  auto AddLocationPtr = [&](std::optional<MemoryLocation> Loc) {
    if (!Loc || !Loc->Ptr) {
      LLVM_DEBUG(
          dbgs() << "[AA] Access to unknown location; -> requires barriers\n");
      return false;
    }
    Ptrs.insert(Loc->Ptr);
    return true;
  };

  if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(&I)) {
    if (!AddLocationPtr(MemoryLocation::getForDest(MI)))
      return true;
    if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(&I))
      if (!AddLocationPtr(MemoryLocation::getForSource(MTI)))
        return true;
  } else if (!AddLocationPtr(MemoryLocation::getOrNone(&I)))
    return true;

  return isPotentiallyAffectedByBarrier(A, Ptrs.getArrayRef(), QueryingAA, &I);
}

bool AA::isPotentiallyAffectedByBarrier(Attributor &A,
                                        ArrayRef<const Value *> Ptrs,
                                        const AbstractAttribute &QueryingAA,
                                        const Instruction *CtxI) {
  for (const Value *Ptr : Ptrs) {
    if (!Ptr) {
      LLVM_DEBUG(dbgs() << "[AA] nullptr; -> requires barriers\n");
      return true;
    }

    auto Pred = [&](Value &Obj) {
      if (AA::isAssumedThreadLocalObject(A, Obj, QueryingAA))
        return true;
      LLVM_DEBUG(dbgs() << "[AA] Access to '" << Obj << "' via '" << *Ptr
                        << "'; -> requires barrier\n");
      return false;
    };

    const auto *UnderlyingObjsAA = A.getAAFor<AAUnderlyingObjects>(
        QueryingAA, IRPosition::value(*Ptr), DepClassTy::OPTIONAL);
    if (!UnderlyingObjsAA || !UnderlyingObjsAA->forallUnderlyingObjects(Pred))
      return true;
  }
  return false;
}

/// Return true if \p New is equal or worse than \p Old.
static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) {
  if (!Old.isIntAttribute())
    return true;

  return Old.getValueAsInt() >= New.getValueAsInt();
}

/// Return true if the information provided by \p Attr was added to the
/// attribute set \p AttrSet. This is only the case if it was not already
/// present in \p AttrSet.
static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr,
                             AttributeSet AttrSet, bool ForceReplace,
                             AttrBuilder &AB) {

  if (Attr.isEnumAttribute()) {
    Attribute::AttrKind Kind = Attr.getKindAsEnum();
    if (AttrSet.hasAttribute(Kind))
      return false;
    AB.addAttribute(Kind);
    return true;
  }
  if (Attr.isStringAttribute()) {
    StringRef Kind = Attr.getKindAsString();
    if (AttrSet.hasAttribute(Kind)) {
      if (!ForceReplace)
        return false;
    }
    AB.addAttribute(Kind, Attr.getValueAsString());
    return true;
  }
  if (Attr.isIntAttribute()) {
    Attribute::AttrKind Kind = Attr.getKindAsEnum();
    if (!ForceReplace && Kind == Attribute::Memory) {
      MemoryEffects ME = Attr.getMemoryEffects() & AttrSet.getMemoryEffects();
      if (ME == AttrSet.getMemoryEffects())
        return false;
      AB.addMemoryAttr(ME);
      return true;
    }
    if (AttrSet.hasAttribute(Kind)) {
      if (!ForceReplace && isEqualOrWorse(Attr, AttrSet.getAttribute(Kind)))
        return false;
    }
    AB.addAttribute(Attr);
    return true;
  }
  if (Attr.isConstantRangeAttribute()) {
    Attribute::AttrKind Kind = Attr.getKindAsEnum();
    if (!ForceReplace && AttrSet.hasAttribute(Kind))
      return false;
    AB.addAttribute(Attr);
    return true;
  }

  llvm_unreachable("Expected enum or string attribute!");
}

Argument *IRPosition::getAssociatedArgument() const {
  if (getPositionKind() == IRP_ARGUMENT)
    return cast<Argument>(&getAnchorValue());

  // Not an Argument and no argument number means this is not a call site
  // argument, thus we cannot find a callback argument to return.
  int ArgNo = getCallSiteArgNo();
  if (ArgNo < 0)
    return nullptr;

  // Use abstract call sites to make the connection between the call site
  // values and the ones in callbacks. If a callback was found that makes use
  // of the underlying call site operand, we want the corresponding callback
  // callee argument and not the direct callee argument.
  std::optional<Argument *> CBCandidateArg;
  SmallVector<const Use *, 4> CallbackUses;
  const auto &CB = cast<CallBase>(getAnchorValue());
  AbstractCallSite::getCallbackUses(CB, CallbackUses);
  for (const Use *U : CallbackUses) {
    AbstractCallSite ACS(U);
    assert(ACS && ACS.isCallbackCall());
    if (!ACS.getCalledFunction())
      continue;

    for (unsigned u = 0, e = ACS.getNumArgOperands(); u < e; u++) {

      // Test if the underlying call site operand is argument number u of the
      // callback callee.
      if (ACS.getCallArgOperandNo(u) != ArgNo)
        continue;

      assert(ACS.getCalledFunction()->arg_size() > u &&
             "ACS mapped into var-args arguments!");
      if (CBCandidateArg) {
        CBCandidateArg = nullptr;
        break;
      }
      CBCandidateArg = ACS.getCalledFunction()->getArg(u);
    }
  }

  // If we found a unique callback candidate argument, return it.
  if (CBCandidateArg && *CBCandidateArg)
    return *CBCandidateArg;

  // If no callbacks were found, or none used the underlying call site operand
  // exclusively, use the direct callee argument if available.
  auto *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
  if (Callee && Callee->arg_size() > unsigned(ArgNo))
    return Callee->getArg(ArgNo);

  return nullptr;
}

ChangeStatus AbstractAttribute::update(Attributor &A) {
  ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
  if (getState().isAtFixpoint())
    return HasChanged;

  LLVM_DEBUG(dbgs() << "[Attributor] Update: " << *this << "\n");

  HasChanged = updateImpl(A);

  LLVM_DEBUG(dbgs() << "[Attributor] Update " << HasChanged << " " << *this
                    << "\n");

  return HasChanged;
}

Attributor::Attributor(SetVector<Function *> &Functions,
                       InformationCache &InfoCache,
                       AttributorConfig Configuration)
    : Allocator(InfoCache.Allocator), Functions(Functions),
      InfoCache(InfoCache), Configuration(Configuration) {
  if (!isClosedWorldModule())
    return;
  for (Function *Fn : Functions)
    if (Fn->hasAddressTaken(/*PutOffender=*/nullptr,
                            /*IgnoreCallbackUses=*/false,
                            /*IgnoreAssumeLikeCalls=*/true,
                            /*IgnoreLLVMUsed=*/true,
                            /*IgnoreARCAttachedCall=*/false,
                            /*IgnoreCastedDirectCall=*/true))
      InfoCache.IndirectlyCallableFunctions.push_back(Fn);
}

bool Attributor::getAttrsFromAssumes(const IRPosition &IRP,
                                     Attribute::AttrKind AK,
                                     SmallVectorImpl<Attribute> &Attrs) {
  assert(IRP.getPositionKind() != IRPosition::IRP_INVALID &&
         "Did expect a valid position!");
  MustBeExecutedContextExplorer *Explorer =
      getInfoCache().getMustBeExecutedContextExplorer();
  if (!Explorer)
    return false;

  Value &AssociatedValue = IRP.getAssociatedValue();

  const Assume2KnowledgeMap &A2K =
      getInfoCache().getKnowledgeMap().lookup({&AssociatedValue, AK});

  // Check if we found any potential assume use, if not we don't need to create
  // explorer iterators.
  if (A2K.empty())
    return false;

  LLVMContext &Ctx = AssociatedValue.getContext();
  unsigned AttrsSize = Attrs.size();
  auto EIt = Explorer->begin(IRP.getCtxI()),
       EEnd = Explorer->end(IRP.getCtxI());
  for (const auto &It : A2K)
    if (Explorer->findInContextOf(It.first, EIt, EEnd))
      Attrs.push_back(Attribute::get(Ctx, AK, It.second.Max));
  return AttrsSize != Attrs.size();
}

template <typename DescTy>
ChangeStatus
Attributor::updateAttrMap(const IRPosition &IRP, ArrayRef<DescTy> AttrDescs,
                          function_ref<bool(const DescTy &, AttributeSet,
                                            AttributeMask &, AttrBuilder &)>
                              CB) {
  if (AttrDescs.empty())
    return ChangeStatus::UNCHANGED;
  switch (IRP.getPositionKind()) {
  case IRPosition::IRP_FLOAT:
  case IRPosition::IRP_INVALID:
    return ChangeStatus::UNCHANGED;
  default:
    break;
  };

  AttributeList AL = IRP.getAttrList();
  Value *AttrListAnchor = IRP.getAttrListAnchor();
  auto [Iter, Inserted] = AttrsMap.insert({AttrListAnchor, AL});
  if (!Inserted)
    AL = Iter->second;

  LLVMContext &Ctx = IRP.getAnchorValue().getContext();
  auto AttrIdx = IRP.getAttrIdx();
  AttributeSet AS = AL.getAttributes(AttrIdx);
  AttributeMask AM;
  AttrBuilder AB(Ctx);

  ChangeStatus HasChanged = ChangeStatus::UNCHANGED;
  for (const DescTy &AttrDesc : AttrDescs)
    if (CB(AttrDesc, AS, AM, AB))
      HasChanged = ChangeStatus::CHANGED;

  if (HasChanged == ChangeStatus::UNCHANGED)
    return ChangeStatus::UNCHANGED;

  AL = AL.removeAttributesAtIndex(Ctx, AttrIdx, AM);
  AL = AL.addAttributesAtIndex(Ctx, AttrIdx, AB);

  Iter->second = AL;
  return HasChanged;
}

bool Attributor::hasAttr(const IRPosition &IRP,
                         ArrayRef<Attribute::AttrKind> AttrKinds,
                         bool IgnoreSubsumingPositions,
                         Attribute::AttrKind ImpliedAttributeKind) {
  bool Implied = false;
  bool HasAttr = false;
  auto HasAttrCB = [&](const Attribute::AttrKind &Kind, AttributeSet AttrSet,
                       AttributeMask &, AttrBuilder &) {
    if (AttrSet.hasAttribute(Kind)) {
      Implied |= Kind != ImpliedAttributeKind;
      HasAttr = true;
    }
    return false;
  };
  for (const IRPosition &EquivIRP : SubsumingPositionIterator(IRP)) {
    updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, HasAttrCB);
    if (HasAttr)
      break;
    // The first position returned by the SubsumingPositionIterator is
    // always the position itself. If we ignore subsuming positions we
    // are done after the first iteration.
    if (IgnoreSubsumingPositions)
      break;
    Implied = true;
  }
  if (!HasAttr) {
    Implied = true;
    SmallVector<Attribute> Attrs;
    for (Attribute::AttrKind AK : AttrKinds)
      if (getAttrsFromAssumes(IRP, AK, Attrs)) {
        HasAttr = true;
        break;
      }
  }

  // Check if we should manifest the implied attribute kind at the IRP.
  if (ImpliedAttributeKind != Attribute::None && HasAttr && Implied)
    manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(),
                                       ImpliedAttributeKind)});
  return HasAttr;
}

void Attributor::getAttrs(const IRPosition &IRP,
                          ArrayRef<Attribute::AttrKind> AttrKinds,
                          SmallVectorImpl<Attribute> &Attrs,
                          bool IgnoreSubsumingPositions) {
  auto CollectAttrCB = [&](const Attribute::AttrKind &Kind,
                           AttributeSet AttrSet, AttributeMask &,
                           AttrBuilder &) {
    if (AttrSet.hasAttribute(Kind))
      Attrs.push_back(AttrSet.getAttribute(Kind));
    return false;
  };
  for (const IRPosition &EquivIRP : SubsumingPositionIterator(IRP)) {
    updateAttrMap<Attribute::AttrKind>(EquivIRP, AttrKinds, CollectAttrCB);
    // The first position returned by the SubsumingPositionIterator is
    // always the position itself. If we ignore subsuming positions we
    // are done after the first iteration.
    if (IgnoreSubsumingPositions)
      break;
  }
  for (Attribute::AttrKind AK : AttrKinds)
    getAttrsFromAssumes(IRP, AK, Attrs);
}

ChangeStatus Attributor::removeAttrs(const IRPosition &IRP,
                                     ArrayRef<Attribute::AttrKind> AttrKinds) {
  auto RemoveAttrCB = [&](const Attribute::AttrKind &Kind, AttributeSet AttrSet,
                          AttributeMask &AM, AttrBuilder &) {
    if (!AttrSet.hasAttribute(Kind))
      return false;
    AM.addAttribute(Kind);
    return true;
  };
  return updateAttrMap<Attribute::AttrKind>(IRP, AttrKinds, RemoveAttrCB);
}

ChangeStatus Attributor::removeAttrs(const IRPosition &IRP,
                                     ArrayRef<StringRef> Attrs) {
  auto RemoveAttrCB = [&](StringRef Attr, AttributeSet AttrSet,
                          AttributeMask &AM, AttrBuilder &) -> bool {
    if (!AttrSet.hasAttribute(Attr))
      return false;
    AM.addAttribute(Attr);
    return true;
  };

  return updateAttrMap<StringRef>(IRP, Attrs, RemoveAttrCB);
}

ChangeStatus Attributor::manifestAttrs(const IRPosition &IRP,
                                       ArrayRef<Attribute> Attrs,
                                       bool ForceReplace) {
  LLVMContext &Ctx = IRP.getAnchorValue().getContext();
  auto AddAttrCB = [&](const Attribute &Attr, AttributeSet AttrSet,
                       AttributeMask &, AttrBuilder &AB) {
    return addIfNotExistent(Ctx, Attr, AttrSet, ForceReplace, AB);
  };
  return updateAttrMap<Attribute>(IRP, Attrs, AddAttrCB);
}

SubsumingPositionIterator::SubsumingPositionIterator(const IRPosition &IRP) {
  IRPositions.emplace_back(IRP);

  // Helper to determine if operand bundles on a call site are benign or
  // potentially problematic. We handle only llvm.assume for now.
  auto CanIgnoreOperandBundles = [](const CallBase &CB) {
    return (isa<IntrinsicInst>(CB) &&
            cast<IntrinsicInst>(CB).getIntrinsicID() == Intrinsic ::assume);
  };

  const auto *CB = dyn_cast<CallBase>(&IRP.getAnchorValue());
  switch (IRP.getPositionKind()) {
  case IRPosition::IRP_INVALID:
  case IRPosition::IRP_FLOAT:
  case IRPosition::IRP_FUNCTION:
    return;
  case IRPosition::IRP_ARGUMENT:
  case IRPosition::IRP_RETURNED:
    IRPositions.emplace_back(IRPosition::function(*IRP.getAnchorScope()));
    return;
  case IRPosition::IRP_CALL_SITE:
    assert(CB && "Expected call site!");
    // TODO: We need to look at the operand bundles similar to the redirection
    //       in CallBase.
    if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB))
      if (auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand()))
        IRPositions.emplace_back(IRPosition::function(*Callee));
    return;
  case IRPosition::IRP_CALL_SITE_RETURNED:
    assert(CB && "Expected call site!");
    // TODO: We need to look at the operand bundles similar to the redirection
    //       in CallBase.
    if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
      if (auto *Callee =
              dyn_cast_if_present<Function>(CB->getCalledOperand())) {
        IRPositions.emplace_back(IRPosition::returned(*Callee));
        IRPositions.emplace_back(IRPosition::function(*Callee));
        for (const Argument &Arg : Callee->args())
          if (Arg.hasReturnedAttr()) {
            IRPositions.emplace_back(
                IRPosition::callsite_argument(*CB, Arg.getArgNo()));
            IRPositions.emplace_back(
                IRPosition::value(*CB->getArgOperand(Arg.getArgNo())));
            IRPositions.emplace_back(IRPosition::argument(Arg));
          }
      }
    }
    IRPositions.emplace_back(IRPosition::callsite_function(*CB));
    return;
  case IRPosition::IRP_CALL_SITE_ARGUMENT: {
    assert(CB && "Expected call site!");
    // TODO: We need to look at the operand bundles similar to the redirection
    //       in CallBase.
    if (!CB->hasOperandBundles() || CanIgnoreOperandBundles(*CB)) {
      auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
      if (Callee) {
        if (Argument *Arg = IRP.getAssociatedArgument())
          IRPositions.emplace_back(IRPosition::argument(*Arg));
        IRPositions.emplace_back(IRPosition::function(*Callee));
      }
    }
    IRPositions.emplace_back(IRPosition::value(IRP.getAssociatedValue()));
    return;
  }
  }
}

void IRPosition::verify() {
#ifdef EXPENSIVE_CHECKS
  switch (getPositionKind()) {
  case IRP_INVALID:
    assert((CBContext == nullptr) &&
           "Invalid position must not have CallBaseContext!");
    assert(!Enc.getOpaqueValue() &&
           "Expected a nullptr for an invalid position!");
    return;
  case IRP_FLOAT:
    assert((!isa<Argument>(&getAssociatedValue())) &&
           "Expected specialized kind for argument values!");
    return;
  case IRP_RETURNED:
    assert(isa<Function>(getAsValuePtr()) &&
           "Expected function for a 'returned' position!");
    assert(getAsValuePtr() == &getAssociatedValue() &&
           "Associated value mismatch!");
    return;
  case IRP_CALL_SITE_RETURNED:
    assert((CBContext == nullptr) &&
           "'call site returned' position must not have CallBaseContext!");
    assert((isa<CallBase>(getAsValuePtr())) &&
           "Expected call base for 'call site returned' position!");
    assert(getAsValuePtr() == &getAssociatedValue() &&
           "Associated value mismatch!");
    return;
  case IRP_CALL_SITE:
    assert((CBContext == nullptr) &&
           "'call site function' position must not have CallBaseContext!");
    assert((isa<CallBase>(getAsValuePtr())) &&
           "Expected call base for 'call site function' position!");
    assert(getAsValuePtr() == &getAssociatedValue() &&
           "Associated value mismatch!");
    return;
  case IRP_FUNCTION:
    assert(isa<Function>(getAsValuePtr()) &&
           "Expected function for a 'function' position!");
    assert(getAsValuePtr() == &getAssociatedValue() &&
           "Associated value mismatch!");
    return;
  case IRP_ARGUMENT:
    assert(isa<Argument>(getAsValuePtr()) &&
           "Expected argument for a 'argument' position!");
    assert(getAsValuePtr() == &getAssociatedValue() &&
           "Associated value mismatch!");
    return;
  case IRP_CALL_SITE_ARGUMENT: {
    assert((CBContext == nullptr) &&
           "'call site argument' position must not have CallBaseContext!");
    Use *U = getAsUsePtr();
    (void)U; // Silence unused variable warning.
    assert(U && "Expected use for a 'call site argument' position!");
    assert(isa<CallBase>(U->getUser()) &&
           "Expected call base user for a 'call site argument' position!");
    assert(cast<CallBase>(U->getUser())->isArgOperand(U) &&
           "Expected call base argument operand for a 'call site argument' "
           "position");
    assert(cast<CallBase>(U->getUser())->getArgOperandNo(U) ==
               unsigned(getCallSiteArgNo()) &&
           "Argument number mismatch!");
    assert(U->get() == &getAssociatedValue() && "Associated value mismatch!");
    return;
  }
  }
#endif
}

std::optional<Constant *>
Attributor::getAssumedConstant(const IRPosition &IRP,
                               const AbstractAttribute &AA,
                               bool &UsedAssumedInformation) {
  // First check all callbacks provided by outside AAs. If any of them returns
  // a non-null value that is different from the associated value, or
  // std::nullopt, we assume it's simplified.
  for (auto &CB : SimplificationCallbacks.lookup(IRP)) {
    std::optional<Value *> SimplifiedV = CB(IRP, &AA, UsedAssumedInformation);
    if (!SimplifiedV)
      return std::nullopt;
    if (isa_and_nonnull<Constant>(*SimplifiedV))
      return cast<Constant>(*SimplifiedV);
    return nullptr;
  }
  if (auto *C = dyn_cast<Constant>(&IRP.getAssociatedValue()))
    return C;
  SmallVector<AA::ValueAndContext> Values;
  if (getAssumedSimplifiedValues(IRP, &AA, Values,
                                 AA::ValueScope::Interprocedural,
                                 UsedAssumedInformation)) {
    if (Values.empty())
      return std::nullopt;
    if (auto *C = dyn_cast_or_null<Constant>(
            AAPotentialValues::getSingleValue(*this, AA, IRP, Values)))
      return C;
  }
  return nullptr;
}

std::optional<Value *> Attributor::getAssumedSimplified(
    const IRPosition &IRP, const AbstractAttribute *AA,
    bool &UsedAssumedInformation, AA::ValueScope S) {
  // First check all callbacks provided by outside AAs. If any of them returns
  // a non-null value that is different from the associated value, or
  // std::nullopt, we assume it's simplified.
  for (auto &CB : SimplificationCallbacks.lookup(IRP))
    return CB(IRP, AA, UsedAssumedInformation);

  SmallVector<AA::ValueAndContext> Values;
  if (!getAssumedSimplifiedValues(IRP, AA, Values, S, UsedAssumedInformation))
    return &IRP.getAssociatedValue();
  if (Values.empty())
    return std::nullopt;
  if (AA)
    if (Value *V = AAPotentialValues::getSingleValue(*this, *AA, IRP, Values))
      return V;
  if (IRP.getPositionKind() == IRPosition::IRP_RETURNED ||
      IRP.getPositionKind() == IRPosition::IRP_CALL_SITE_RETURNED)
    return nullptr;
  return &IRP.getAssociatedValue();
}

bool Attributor::getAssumedSimplifiedValues(
    const IRPosition &InitialIRP, const AbstractAttribute *AA,
    SmallVectorImpl<AA::ValueAndContext> &Values, AA::ValueScope S,
    bool &UsedAssumedInformation, bool RecurseForSelectAndPHI) {
  SmallPtrSet<Value *, 8> Seen;
  SmallVector<IRPosition, 8> Worklist;
  Worklist.push_back(InitialIRP);
  while (!Worklist.empty()) {
    const IRPosition &IRP = Worklist.pop_back_val();

    // First check all callbacks provided by outside AAs. If any of them returns
    // a non-null value that is different from the associated value, or
    // std::nullopt, we assume it's simplified.
    int NV = Values.size();
    const auto &SimplificationCBs = SimplificationCallbacks.lookup(IRP);
    for (const auto &CB : SimplificationCBs) {
      std::optional<Value *> CBResult = CB(IRP, AA, UsedAssumedInformation);
      if (!CBResult.has_value())
        continue;
      Value *V = *CBResult;
      if (!V)
        return false;
      if ((S & AA::ValueScope::Interprocedural) ||
          AA::isValidInScope(*V, IRP.getAnchorScope()))
        Values.push_back(AA::ValueAndContext{*V, nullptr});
      else
        return false;
    }
    if (SimplificationCBs.empty()) {
      // If no high-level/outside simplification occurred, use
      // AAPotentialValues.
      const auto *PotentialValuesAA =
          getOrCreateAAFor<AAPotentialValues>(IRP, AA, DepClassTy::OPTIONAL);
      if (PotentialValuesAA &&
          PotentialValuesAA->getAssumedSimplifiedValues(*this, Values, S)) {
        UsedAssumedInformation |= !PotentialValuesAA->isAtFixpoint();
      } else if (IRP.getPositionKind() != IRPosition::IRP_RETURNED) {
        Values.push_back({IRP.getAssociatedValue(), IRP.getCtxI()});
      } else {
        // TODO: We could visit all returns and add the operands.
        return false;
      }
    }

    if (!RecurseForSelectAndPHI)
      break;

    for (int I = NV, E = Values.size(); I < E; ++I) {
      Value *V = Values[I].getValue();
      if (!isa<PHINode>(V) && !isa<SelectInst>(V))
        continue;
      if (!Seen.insert(V).second)
        continue;
      // Move the last element to this slot.
      Values[I] = Values[E - 1];
      // Eliminate the last slot, adjust the indices.
      Values.pop_back();
      --E;
      --I;
      // Add a new value (select or phi) to the worklist.
      Worklist.push_back(IRPosition::value(*V));
    }
  }
  return true;
}

std::optional<Value *> Attributor::translateArgumentToCallSiteContent(
    std::optional<Value *> V, CallBase &CB, const AbstractAttribute &AA,
    bool &UsedAssumedInformation) {
  if (!V)
    return V;
  if (*V == nullptr || isa<Constant>(*V))
    return V;
  if (auto *Arg = dyn_cast<Argument>(*V))
    if (CB.getCalledOperand() == Arg->getParent() &&
        CB.arg_size() > Arg->getArgNo())
      if (!Arg->hasPointeeInMemoryValueAttr())
        return getAssumedSimplified(
            IRPosition::callsite_argument(CB, Arg->getArgNo()), AA,
            UsedAssumedInformation, AA::Intraprocedural);
  return nullptr;
}

Attributor::~Attributor() {
  // The abstract attributes are allocated via the BumpPtrAllocator Allocator,
  // thus we cannot delete them. We can, and want to, destruct them though.
  for (auto &It : AAMap) {
    AbstractAttribute *AA = It.getSecond();
    AA->~AbstractAttribute();
  }
}

bool Attributor::isAssumedDead(const AbstractAttribute &AA,
                               const AAIsDead *FnLivenessAA,
                               bool &UsedAssumedInformation,
                               bool CheckBBLivenessOnly, DepClassTy DepClass) {
  if (!Configuration.UseLiveness)
    return false;
  const IRPosition &IRP = AA.getIRPosition();
  if (!Functions.count(IRP.getAnchorScope()))
    return false;
  return isAssumedDead(IRP, &AA, FnLivenessAA, UsedAssumedInformation,
                       CheckBBLivenessOnly, DepClass);
}

bool Attributor::isAssumedDead(const Use &U,
                               const AbstractAttribute *QueryingAA,
                               const AAIsDead *FnLivenessAA,
                               bool &UsedAssumedInformation,
                               bool CheckBBLivenessOnly, DepClassTy DepClass) {
  if (!Configuration.UseLiveness)
    return false;
  Instruction *UserI = dyn_cast<Instruction>(U.getUser());
  if (!UserI)
    return isAssumedDead(IRPosition::value(*U.get()), QueryingAA, FnLivenessAA,
                         UsedAssumedInformation, CheckBBLivenessOnly, DepClass);

  if (auto *CB = dyn_cast<CallBase>(UserI)) {
    // For call site argument uses we can check if the argument is
    // unused/dead.
    if (CB->isArgOperand(&U)) {
      const IRPosition &CSArgPos =
          IRPosition::callsite_argument(*CB, CB->getArgOperandNo(&U));
      return isAssumedDead(CSArgPos, QueryingAA, FnLivenessAA,
                           UsedAssumedInformation, CheckBBLivenessOnly,
                           DepClass);
    }
  } else if (ReturnInst *RI = dyn_cast<ReturnInst>(UserI)) {
    const IRPosition &RetPos = IRPosition::returned(*RI->getFunction());
    return isAssumedDead(RetPos, QueryingAA, FnLivenessAA,
                         UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
  } else if (PHINode *PHI = dyn_cast<PHINode>(UserI)) {
    BasicBlock *IncomingBB = PHI->getIncomingBlock(U);
    return isAssumedDead(*IncomingBB->getTerminator(), QueryingAA, FnLivenessAA,
                         UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
  } else if (StoreInst *SI = dyn_cast<StoreInst>(UserI)) {
    if (!CheckBBLivenessOnly && SI->getPointerOperand() != U.get()) {
      const IRPosition IRP = IRPosition::inst(*SI);
      const AAIsDead *IsDeadAA =
          getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);
      if (IsDeadAA && IsDeadAA->isRemovableStore()) {
        if (QueryingAA)
          recordDependence(*IsDeadAA, *QueryingAA, DepClass);
        if (!IsDeadAA->isKnown(AAIsDead::IS_REMOVABLE))
          UsedAssumedInformation = true;
        return true;
      }
    }
  }

  return isAssumedDead(IRPosition::inst(*UserI), QueryingAA, FnLivenessAA,
                       UsedAssumedInformation, CheckBBLivenessOnly, DepClass);
}

bool Attributor::isAssumedDead(const Instruction &I,
                               const AbstractAttribute *QueryingAA,
                               const AAIsDead *FnLivenessAA,
                               bool &UsedAssumedInformation,
                               bool CheckBBLivenessOnly, DepClassTy DepClass,
                               bool CheckForDeadStore) {
  if (!Configuration.UseLiveness)
    return false;
  const IRPosition::CallBaseContext *CBCtx =
      QueryingAA ? QueryingAA->getCallBaseContext() : nullptr;

  if (ManifestAddedBlocks.contains(I.getParent()))
    return false;

  const Function &F = *I.getFunction();
  if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)
    FnLivenessAA = getOrCreateAAFor<AAIsDead>(IRPosition::function(F, CBCtx),
                                              QueryingAA, DepClassTy::NONE);

  // Don't use recursive reasoning.
  if (!FnLivenessAA || QueryingAA == FnLivenessAA)
    return false;

  // If we have a context instruction and a liveness AA we use it.
  if (CheckBBLivenessOnly ? FnLivenessAA->isAssumedDead(I.getParent())
                          : FnLivenessAA->isAssumedDead(&I)) {
    if (QueryingAA)
      recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
    if (!FnLivenessAA->isKnownDead(&I))
      UsedAssumedInformation = true;
    return true;
  }

  if (CheckBBLivenessOnly)
    return false;

  const IRPosition IRP = IRPosition::inst(I, CBCtx);
  const AAIsDead *IsDeadAA =
      getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);

  // Don't use recursive reasoning.
  if (!IsDeadAA || QueryingAA == IsDeadAA)
    return false;

  if (IsDeadAA->isAssumedDead()) {
    if (QueryingAA)
      recordDependence(*IsDeadAA, *QueryingAA, DepClass);
    if (!IsDeadAA->isKnownDead())
      UsedAssumedInformation = true;
    return true;
  }

  if (CheckForDeadStore && isa<StoreInst>(I) && IsDeadAA->isRemovableStore()) {
    if (QueryingAA)
      recordDependence(*IsDeadAA, *QueryingAA, DepClass);
    if (!IsDeadAA->isKnownDead())
      UsedAssumedInformation = true;
    return true;
  }

  return false;
}

bool Attributor::isAssumedDead(const IRPosition &IRP,
                               const AbstractAttribute *QueryingAA,
                               const AAIsDead *FnLivenessAA,
                               bool &UsedAssumedInformation,
                               bool CheckBBLivenessOnly, DepClassTy DepClass) {
  if (!Configuration.UseLiveness)
    return false;
  // Don't check liveness for constants, e.g. functions, used as (floating)
  // values since the context instruction and such is here meaningless.
  if (IRP.getPositionKind() == IRPosition::IRP_FLOAT &&
      isa<Constant>(IRP.getAssociatedValue())) {
    return false;
  }

  Instruction *CtxI = IRP.getCtxI();
  if (CtxI &&
      isAssumedDead(*CtxI, QueryingAA, FnLivenessAA, UsedAssumedInformation,
                    /* CheckBBLivenessOnly */ true,
                    CheckBBLivenessOnly ? DepClass : DepClassTy::OPTIONAL))
    return true;

  if (CheckBBLivenessOnly)
    return false;

  // If we haven't succeeded we query the specific liveness info for the IRP.
  const AAIsDead *IsDeadAA;
  if (IRP.getPositionKind() == IRPosition::IRP_CALL_SITE)
    IsDeadAA = getOrCreateAAFor<AAIsDead>(
        IRPosition::callsite_returned(cast<CallBase>(IRP.getAssociatedValue())),
        QueryingAA, DepClassTy::NONE);
  else
    IsDeadAA = getOrCreateAAFor<AAIsDead>(IRP, QueryingAA, DepClassTy::NONE);

  // Don't use recursive reasoning.
  if (!IsDeadAA || QueryingAA == IsDeadAA)
    return false;

  if (IsDeadAA->isAssumedDead()) {
    if (QueryingAA)
      recordDependence(*IsDeadAA, *QueryingAA, DepClass);
    if (!IsDeadAA->isKnownDead())
      UsedAssumedInformation = true;
    return true;
  }

  return false;
}

bool Attributor::isAssumedDead(const BasicBlock &BB,
                               const AbstractAttribute *QueryingAA,
                               const AAIsDead *FnLivenessAA,
                               DepClassTy DepClass) {
  if (!Configuration.UseLiveness)
    return false;
  const Function &F = *BB.getParent();
  if (!FnLivenessAA || FnLivenessAA->getAnchorScope() != &F)
    FnLivenessAA = getOrCreateAAFor<AAIsDead>(IRPosition::function(F),
                                              QueryingAA, DepClassTy::NONE);

  // Don't use recursive reasoning.
  if (!FnLivenessAA || QueryingAA == FnLivenessAA)
    return false;

  if (FnLivenessAA->isAssumedDead(&BB)) {
    if (QueryingAA)
      recordDependence(*FnLivenessAA, *QueryingAA, DepClass);
    return true;
  }

  return false;
}

bool Attributor::checkForAllCallees(
    function_ref<bool(ArrayRef<const Function *>)> Pred,
    const AbstractAttribute &QueryingAA, const CallBase &CB) {
  if (const Function *Callee = dyn_cast<Function>(CB.getCalledOperand()))
    return Pred(Callee);

  const auto *CallEdgesAA = getAAFor<AACallEdges>(
      QueryingAA, IRPosition::callsite_function(CB), DepClassTy::OPTIONAL);
  if (!CallEdgesAA || CallEdgesAA->hasUnknownCallee())
    return false;

  const auto &Callees = CallEdgesAA->getOptimisticEdges();
  return Pred(Callees.getArrayRef());
}

bool canMarkAsVisited(const User *Usr) {
  return isa<PHINode>(Usr) || !isa<Instruction>(Usr);
}

bool Attributor::checkForAllUses(
    function_ref<bool(const Use &, bool &)> Pred,
    const AbstractAttribute &QueryingAA, const Value &V,
    bool CheckBBLivenessOnly, DepClassTy LivenessDepClass,
    bool IgnoreDroppableUses,
    function_ref<bool(const Use &OldU, const Use &NewU)> EquivalentUseCB) {

  // Check virtual uses first.
  for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&V))
    if (!CB(*this, &QueryingAA))
      return false;

  if (isa<ConstantData>(V))
    return false;

  // Check the trivial case first as it catches void values.
  if (V.use_empty())
    return true;

  const IRPosition &IRP = QueryingAA.getIRPosition();
  SmallVector<const Use *, 16> Worklist;
  SmallPtrSet<const Use *, 16> Visited;

  auto AddUsers = [&](const Value &V, const Use *OldUse) {
    for (const Use &UU : V.uses()) {
      if (OldUse && EquivalentUseCB && !EquivalentUseCB(*OldUse, UU)) {
        LLVM_DEBUG(dbgs() << "[Attributor] Potential copy was "
                             "rejected by the equivalence call back: "
                          << *UU << "!\n");
        return false;
      }

      Worklist.push_back(&UU);
    }
    return true;
  };

  AddUsers(V, /* OldUse */ nullptr);

  LLVM_DEBUG(dbgs() << "[Attributor] Got " << Worklist.size()
                    << " initial uses to check\n");

  const Function *ScopeFn = IRP.getAnchorScope();
  const auto *LivenessAA =
      ScopeFn ? getAAFor<AAIsDead>(QueryingAA, IRPosition::function(*ScopeFn),
                                   DepClassTy::NONE)
              : nullptr;

  while (!Worklist.empty()) {
    const Use *U = Worklist.pop_back_val();
    if (canMarkAsVisited(U->getUser()) && !Visited.insert(U).second)
      continue;
    DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {
      if (auto *Fn = dyn_cast<Function>(U->getUser()))
        dbgs() << "[Attributor] Check use: " << **U << " in " << Fn->getName()
               << "\n";
      else
        dbgs() << "[Attributor] Check use: " << **U << " in " << *U->getUser()
               << "\n";
    });
    bool UsedAssumedInformation = false;
    if (isAssumedDead(*U, &QueryingAA, LivenessAA, UsedAssumedInformation,
                      CheckBBLivenessOnly, LivenessDepClass)) {
      DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                      dbgs() << "[Attributor] Dead use, skip!\n");
      continue;
    }
    if (IgnoreDroppableUses && U->getUser()->isDroppable()) {
      DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                      dbgs() << "[Attributor] Droppable user, skip!\n");
      continue;
    }

    if (auto *SI = dyn_cast<StoreInst>(U->getUser())) {
      if (&SI->getOperandUse(0) == U) {
        if (!Visited.insert(U).second)
          continue;
        SmallSetVector<Value *, 4> PotentialCopies;
        if (AA::getPotentialCopiesOfStoredValue(
                *this, *SI, PotentialCopies, QueryingAA, UsedAssumedInformation,
                /* OnlyExact */ true)) {
          DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                          dbgs()
                              << "[Attributor] Value is stored, continue with "
                              << PotentialCopies.size()
                              << " potential copies instead!\n");
          for (Value *PotentialCopy : PotentialCopies)
            if (!AddUsers(*PotentialCopy, U))
              return false;
          continue;
        }
      }
    }

    bool Follow = false;
    if (!Pred(*U, Follow))
      return false;
    if (!Follow)
      continue;

    User &Usr = *U->getUser();
    AddUsers(Usr, /* OldUse */ nullptr);
  }

  return true;
}

bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
                                      const AbstractAttribute &QueryingAA,
                                      bool RequireAllCallSites,
                                      bool &UsedAssumedInformation) {
  // We can try to determine information from
  // the call sites. However, this is only possible all call sites are known,
  // hence the function has internal linkage.
  const IRPosition &IRP = QueryingAA.getIRPosition();
  const Function *AssociatedFunction = IRP.getAssociatedFunction();
  if (!AssociatedFunction) {
    LLVM_DEBUG(dbgs() << "[Attributor] No function associated with " << IRP
                      << "\n");
    return false;
  }

  return checkForAllCallSites(Pred, *AssociatedFunction, RequireAllCallSites,
                              &QueryingAA, UsedAssumedInformation);
}

bool Attributor::checkForAllCallSites(function_ref<bool(AbstractCallSite)> Pred,
                                      const Function &Fn,
                                      bool RequireAllCallSites,
                                      const AbstractAttribute *QueryingAA,
                                      bool &UsedAssumedInformation,
                                      bool CheckPotentiallyDead) {
  if (RequireAllCallSites && !Fn.hasLocalLinkage()) {
    LLVM_DEBUG(
        dbgs()
        << "[Attributor] Function " << Fn.getName()
        << " has no internal linkage, hence not all call sites are known\n");
    return false;
  }
  // Check virtual uses first.
  for (VirtualUseCallbackTy &CB : VirtualUseCallbacks.lookup(&Fn))
    if (!CB(*this, QueryingAA))
      return false;

  SmallVector<const Use *, 8> Uses(make_pointer_range(Fn.uses()));
  for (unsigned u = 0; u < Uses.size(); ++u) {
    const Use &U = *Uses[u];
    DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {
      if (auto *Fn = dyn_cast<Function>(U))
        dbgs() << "[Attributor] Check use: " << Fn->getName() << " in "
               << *U.getUser() << "\n";
      else
        dbgs() << "[Attributor] Check use: " << *U << " in " << *U.getUser()
               << "\n";
    });
    if (!CheckPotentiallyDead &&
        isAssumedDead(U, QueryingAA, nullptr, UsedAssumedInformation,
                      /* CheckBBLivenessOnly */ true)) {
      DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                      dbgs() << "[Attributor] Dead use, skip!\n");
      continue;
    }
    if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U.getUser())) {
      if (CE->isCast() && CE->getType()->isPointerTy()) {
        DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, {
          dbgs() << "[Attributor] Use, is constant cast expression, add "
                 << CE->getNumUses() << " uses of that expression instead!\n";
        });
        for (const Use &CEU : CE->uses())
          Uses.push_back(&CEU);
        continue;
      }
    }

    AbstractCallSite ACS(&U);
    if (!ACS) {
      LLVM_DEBUG(dbgs() << "[Attributor] Function " << Fn.getName()
                        << " has non call site use " << *U.get() << " in "
                        << *U.getUser() << "\n");
      return false;
    }

    const Use *EffectiveUse =
        ACS.isCallbackCall() ? &ACS.getCalleeUseForCallback() : &U;
    if (!ACS.isCallee(EffectiveUse)) {
      if (!RequireAllCallSites) {
        LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()
                          << " is not a call of " << Fn.getName()
                          << ", skip use\n");
        continue;
      }
      LLVM_DEBUG(dbgs() << "[Attributor] User " << *EffectiveUse->getUser()
                        << " is an invalid use of " << Fn.getName() << "\n");
      return false;
    }

    // Make sure the arguments that can be matched between the call site and the
    // callee argee on their type. It is unlikely they do not and it doesn't
    // make sense for all attributes to know/care about this.
    assert(&Fn == ACS.getCalledFunction() && "Expected known callee");
    unsigned MinArgsParams =
        std::min(size_t(ACS.getNumArgOperands()), Fn.arg_size());
    for (unsigned u = 0; u < MinArgsParams; ++u) {
      Value *CSArgOp = ACS.getCallArgOperand(u);
      if (CSArgOp && Fn.getArg(u)->getType() != CSArgOp->getType()) {
        LLVM_DEBUG(
            dbgs() << "[Attributor] Call site / callee argument type mismatch ["
                   << u << "@" << Fn.getName() << ": "
                   << *Fn.getArg(u)->getType() << " vs. "
                   << *ACS.getCallArgOperand(u)->getType() << "\n");
        return false;
      }
    }

    if (Pred(ACS))
      continue;

    LLVM_DEBUG(dbgs() << "[Attributor] Call site callback failed for "
                      << *ACS.getInstruction() << "\n");
    return false;
  }

  return true;
}

bool Attributor::shouldPropagateCallBaseContext(const IRPosition &IRP) {
  // TODO: Maintain a cache of Values that are
  // on the pathway from a Argument to a Instruction that would effect the
  // liveness/return state etc.
  return EnableCallSiteSpecific;
}

bool Attributor::checkForAllReturnedValues(function_ref<bool(Value &)> Pred,
                                           const AbstractAttribute &QueryingAA,
                                           AA::ValueScope S,
                                           bool RecurseForSelectAndPHI) {

  const IRPosition &IRP = QueryingAA.getIRPosition();
  const Function *AssociatedFunction = IRP.getAssociatedFunction();
  if (!AssociatedFunction)
    return false;

  bool UsedAssumedInformation = false;
  SmallVector<AA::ValueAndContext> Values;
  if (!getAssumedSimplifiedValues(
          IRPosition::returned(*AssociatedFunction), &QueryingAA, Values, S,
          UsedAssumedInformation, RecurseForSelectAndPHI))
    return false;

  return llvm::all_of(Values, [&](const AA::ValueAndContext &VAC) {
    return Pred(*VAC.getValue());
  });
}

static bool checkForAllInstructionsImpl(
    Attributor *A, InformationCache::OpcodeInstMapTy &OpcodeInstMap,
    function_ref<bool(Instruction &)> Pred, const AbstractAttribute *QueryingAA,
    const AAIsDead *LivenessAA, ArrayRef<unsigned> Opcodes,
    bool &UsedAssumedInformation, bool CheckBBLivenessOnly = false,
    bool CheckPotentiallyDead = false) {
  for (unsigned Opcode : Opcodes) {
    // Check if we have instructions with this opcode at all first.
    auto *Insts = OpcodeInstMap.lookup(Opcode);
    if (!Insts)
      continue;

    for (Instruction *I : *Insts) {
      // Skip dead instructions.
      if (A && !CheckPotentiallyDead &&
          A->isAssumedDead(IRPosition::inst(*I), QueryingAA, LivenessAA,
                           UsedAssumedInformation, CheckBBLivenessOnly)) {
        DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                        dbgs() << "[Attributor] Instruction " << *I
                               << " is potentially dead, skip!\n";);
        continue;
      }

      if (!Pred(*I))
        return false;
    }
  }
  return true;
}

bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
                                         const Function *Fn,
                                         const AbstractAttribute *QueryingAA,
                                         ArrayRef<unsigned> Opcodes,
                                         bool &UsedAssumedInformation,
                                         bool CheckBBLivenessOnly,
                                         bool CheckPotentiallyDead) {
  // Since we need to provide instructions we have to have an exact definition.
  if (!Fn || Fn->isDeclaration())
    return false;

  const IRPosition &QueryIRP = IRPosition::function(*Fn);
  const auto *LivenessAA =
      CheckPotentiallyDead && QueryingAA
          ? (getAAFor<AAIsDead>(*QueryingAA, QueryIRP, DepClassTy::NONE))
          : nullptr;

  auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
  if (!checkForAllInstructionsImpl(this, OpcodeInstMap, Pred, QueryingAA,
                                   LivenessAA, Opcodes, UsedAssumedInformation,
                                   CheckBBLivenessOnly, CheckPotentiallyDead))
    return false;

  return true;
}

bool Attributor::checkForAllInstructions(function_ref<bool(Instruction &)> Pred,
                                         const AbstractAttribute &QueryingAA,
                                         ArrayRef<unsigned> Opcodes,
                                         bool &UsedAssumedInformation,
                                         bool CheckBBLivenessOnly,
                                         bool CheckPotentiallyDead) {
  const IRPosition &IRP = QueryingAA.getIRPosition();
  const Function *AssociatedFunction = IRP.getAssociatedFunction();
  return checkForAllInstructions(Pred, AssociatedFunction, &QueryingAA, Opcodes,
                                 UsedAssumedInformation, CheckBBLivenessOnly,
                                 CheckPotentiallyDead);
}

bool Attributor::checkForAllReadWriteInstructions(
    function_ref<bool(Instruction &)> Pred, AbstractAttribute &QueryingAA,
    bool &UsedAssumedInformation) {
  TimeTraceScope TS("checkForAllReadWriteInstructions");

  const Function *AssociatedFunction =
      QueryingAA.getIRPosition().getAssociatedFunction();
  if (!AssociatedFunction)
    return false;

  const IRPosition &QueryIRP = IRPosition::function(*AssociatedFunction);
  const auto *LivenessAA =
      getAAFor<AAIsDead>(QueryingAA, QueryIRP, DepClassTy::NONE);

  for (Instruction *I :
       InfoCache.getReadOrWriteInstsForFunction(*AssociatedFunction)) {
    // Skip dead instructions.
    if (isAssumedDead(IRPosition::inst(*I), &QueryingAA, LivenessAA,
                      UsedAssumedInformation))
      continue;

    if (!Pred(*I))
      return false;
  }

  return true;
}

void Attributor::runTillFixpoint() {
  TimeTraceScope TimeScope("Attributor::runTillFixpoint");
  LLVM_DEBUG(dbgs() << "[Attributor] Identified and initialized "
                    << DG.SyntheticRoot.Deps.size()
                    << " abstract attributes.\n");

  // Now that all abstract attributes are collected and initialized we start
  // the abstract analysis.

  unsigned IterationCounter = 1;
  unsigned MaxIterations =
      Configuration.MaxFixpointIterations.value_or(SetFixpointIterations);

  SmallVector<AbstractAttribute *, 32> ChangedAAs;
  SetVector<AbstractAttribute *> Worklist, InvalidAAs;
  Worklist.insert_range(DG.SyntheticRoot);

  do {
    // Remember the size to determine new attributes.
    size_t NumAAs = DG.SyntheticRoot.Deps.size();
    LLVM_DEBUG(dbgs() << "\n\n[Attributor] #Iteration: " << IterationCounter
                      << ", Worklist size: " << Worklist.size() << "\n");

    // For invalid AAs we can fix dependent AAs that have a required dependence,
    // thereby folding long dependence chains in a single step without the need
    // to run updates.
    for (unsigned u = 0; u < InvalidAAs.size(); ++u) {
      AbstractAttribute *InvalidAA = InvalidAAs[u];

      // Check the dependences to fast track invalidation.
      DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                      dbgs() << "[Attributor] InvalidAA: " << *InvalidAA
                             << " has " << InvalidAA->Deps.size()
                             << " required & optional dependences\n");
      for (auto &DepIt : InvalidAA->Deps) {
        AbstractAttribute *DepAA = cast<AbstractAttribute>(DepIt.getPointer());
        if (DepIt.getInt() == unsigned(DepClassTy::OPTIONAL)) {
          DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE,
                          dbgs() << " - recompute: " << *DepAA);
          Worklist.insert(DepAA);
          continue;
        }
        DEBUG_WITH_TYPE(VERBOSE_DEBUG_TYPE, dbgs()
                                                << " - invalidate: " << *DepAA);
        DepAA->getState().indicatePessimisticFixpoint();
        assert(DepAA->getState().isAtFixpoint() && "Expected fixpoint state!");
        if (!DepAA->getState().isValidState())
          InvalidAAs.insert(DepAA);
        else
          ChangedAAs.push_back(DepAA);
      }
      InvalidAA->Deps.clear();
    }

    // Add all abstract attributes that are potentially dependent on one that
    // changed to the work list.
    for (AbstractAttribute *ChangedAA : ChangedAAs) {
      for (auto &DepIt : ChangedAA->Deps)
        Worklist.insert(cast<AbstractAttribute>(DepIt.getPointer()));
      ChangedAA->Deps.clear();
    }

    LLVM_DEBUG(dbgs() << "[Attributor] #Iteration: " << IterationCounter
                      << ", Worklist+Dependent size: " << Worklist.size()
                      << "\n");

    // Reset the changed and invalid set.
    ChangedAAs.clear();
    InvalidAAs.clear();

    // Update all abstract attribute in the work list and record the ones that
    // changed.
    for (AbstractAttribute *AA : Worklist) {
      const auto &AAState = AA->getState();
      if (!AAState.isAtFixpoint())
        if (updateAA(*AA) == ChangeStatus::CHANGED)
          ChangedAAs.push_back(AA);

      // Use the InvalidAAs vector to propagate invalid states fast transitively
      // without requiring updates.
      if (!AAState.isValidState())
        InvalidAAs.insert(AA);
    }

    // Add attributes to the changed set if they have been created in the last
    // iteration.
    ChangedAAs.append(DG.SyntheticRoot.begin() + NumAAs,
                      DG.SyntheticRoot.end());

    // Reset the work list and repopulate with the changed abstract attributes.
    // Note that dependent ones are added above.
    Worklist.clear();
    Worklist.insert_range(ChangedAAs);
    Worklist.insert_range(QueryAAsAwaitingUpdate);
    QueryAAsAwaitingUpdate.clear();

  } while (!Worklist.empty() && (IterationCounter++ < MaxIterations));

  if (IterationCounter > MaxIterations && !Functions.empty()) {
    auto Remark = [&](OptimizationRemarkMissed ORM) {
      return ORM << "Attributor did not reach a fixpoint after "
                 << ore::NV("Iterations", MaxIterations) << " iterations.";
    };
    Function *F = Functions.front();
    emitRemark<OptimizationRemarkMissed>(F, "FixedPoint", Remark);
  }

  LLVM_DEBUG(dbgs() << "\n[Attributor] Fixpoint iteration done after: "
                    << IterationCounter << "/" << MaxIterations
                    << " iterations\n");

  // Reset abstract arguments not settled in a sound fixpoint by now. This
  // happens when we stopped the fixpoint iteration early. Note that only the
  // ones marked as "changed" *and* the ones transitively depending on them
  // need to be reverted to a pessimistic state. Others might not be in a
  // fixpoint state but we can use the optimistic results for them anyway.
  SmallPtrSet<AbstractAttribute *, 32> Visited;
  for (unsigned u = 0; u < ChangedAAs.size(); u++) {
    AbstractAttribute *ChangedAA = ChangedAAs[u];
    if (!Visited.insert(ChangedAA).second)
      continue;

    AbstractState &State = ChangedAA->getState();
    if (!State.isAtFixpoint()) {
      State.indicatePessimisticFixpoint();

      NumAttributesTimedOut++;
    }

    for (auto &DepIt : ChangedAA->Deps)
      ChangedAAs.push_back(cast<AbstractAttribute>(DepIt.getPointer()));
    ChangedAA->Deps.clear();
  }

  LLVM_DEBUG({
    if (!Visited.empty())
      dbgs() << "\n[Attributor] Finalized " << Visited.size()
             << " abstract attributes.\n";
  });
}

void Attributor::registerForUpdate(AbstractAttribute &AA) {
  assert(AA.isQueryAA() &&
         "Non-query AAs should not be required to register for updates!");
  QueryAAsAwaitingUpdate.insert(&AA);
}

ChangeStatus Attributor::manifestAttributes() {
  TimeTraceScope TimeScope("Attributor::manifestAttributes");
  size_t NumFinalAAs = DG.SyntheticRoot.Deps.size();

  unsigned NumManifested = 0;
  unsigned NumAtFixpoint = 0;
  ChangeStatus ManifestChange = ChangeStatus::UNCHANGED;
  for (auto &DepAA : DG.SyntheticRoot.Deps) {
    AbstractAttribute *AA = cast<AbstractAttribute>(DepAA.getPointer());
    AbstractState &State = AA->getState();

    // If there is not already a fixpoint reached, we can now take the
    // optimistic state. This is correct because we enforced a pessimistic one
    // on abstract attributes that were transitively dependent on a changed one
    // already above.
    if (!State.isAtFixpoint())
      State.indicateOptimisticFixpoint();

    // We must not manifest Attributes that use Callbase info.
    if (AA->hasCallBaseContext())
      continue;
    // If the state is invalid, we do not try to manifest it.
    if (!State.isValidState())
      continue;

    if (AA->getCtxI() && !isRunOn(*AA->getAnchorScope()))
      continue;

    // Skip dead code.
    bool UsedAssumedInformation = false;
    if (isAssumedDead(*AA, nullptr, UsedAssumedInformation,
                      /* CheckBBLivenessOnly */ true))
      continue;
    // Check if the manifest debug counter that allows skipping manifestation of
    // AAs
    if (!DebugCounter::shouldExecute(ManifestDBGCounter))
      continue;
    // Manifest the state and record if we changed the IR.
    ChangeStatus LocalChange = AA->manifest(*this);
    if (LocalChange == ChangeStatus::CHANGED && AreStatisticsEnabled())
      AA->trackStatistics();
    LLVM_DEBUG(dbgs() << "[Attributor] Manifest " << LocalChange << " : " << *AA
                      << "\n");

    ManifestChange = ManifestChange | LocalChange;

    NumAtFixpoint++;
    NumManifested += (LocalChange == ChangeStatus::CHANGED);
  }

  (void)NumManifested;
  (void)NumAtFixpoint;
  LLVM_DEBUG(dbgs() << "\n[Attributor] Manifested " << NumManifested
                    << " arguments while " << NumAtFixpoint
                    << " were in a valid fixpoint state\n");

  NumAttributesManifested += NumManifested;
  NumAttributesValidFixpoint += NumAtFixpoint;

  (void)NumFinalAAs;
  if (NumFinalAAs != DG.SyntheticRoot.Deps.size()) {
    auto DepIt = DG.SyntheticRoot.Deps.begin();
    for (unsigned u = 0; u < NumFinalAAs; ++u)
      ++DepIt;
    for (unsigned u = NumFinalAAs; u < DG.SyntheticRoot.Deps.size();
         ++u, ++DepIt) {
      errs() << "Unexpected abstract attribute: "
             << cast<AbstractAttribute>(DepIt->getPointer()) << " :: "
             << cast<AbstractAttribute>(DepIt->getPointer())
                    ->getIRPosition()
                    .getAssociatedValue()
             << "\n";
    }
    llvm_unreachable("Expected the final number of abstract attributes to "
                     "remain unchanged!");
  }

  for (auto &It : AttrsMap) {
    AttributeList &AL = It.getSecond();
    const IRPosition &IRP =
        isa<Function>(It.getFirst())
            ? IRPosition::function(*cast<Function>(It.getFirst()))
            : IRPosition::callsite_function(*cast<CallBase>(It.getFirst()));
    IRP.setAttrList(AL);
  }

  return ManifestChange;
}

void Attributor::identifyDeadInternalFunctions() {
  // Early exit if we don't intend to delete functions.
  if (!Configuration.DeleteFns)
    return;

  // To avoid triggering an assertion in the lazy call graph we will not delete
  // any internal library functions. We should modify the assertion though and
  // allow internals to be deleted.
  const auto *TLI =
      isModulePass()
          ? nullptr
          : getInfoCache().getTargetLibraryInfoForFunction(*Functions.back());
  LibFunc LF;

  // Identify dead internal functions and delete them. This happens outside
  // the other fixpoint analysis as we might treat potentially dead functions
  // as live to lower the number of iterations. If they happen to be dead, the
  // below fixpoint loop will identify and eliminate them.

  SmallVector<Function *, 8> InternalFns;
  for (Function *F : Functions)
    if (F->hasLocalLinkage() && (isModulePass() || !TLI->getLibFunc(*F, LF)))
      InternalFns.push_back(F);

  SmallPtrSet<Function *, 8> LiveInternalFns;
  bool FoundLiveInternal = true;
  while (FoundLiveInternal) {
    FoundLiveInternal = false;
    for (Function *&F : InternalFns) {
      if (!F)
        continue;

      bool UsedAssumedInformation = false;
      if (checkForAllCallSites(
              [&](AbstractCallSite ACS) {
                Function *Callee = ACS.getInstruction()->getFunction();
                return ToBeDeletedFunctions.count(Callee) ||
                       (Functions.count(Callee) && Callee->hasLocalLinkage() &&
                        !LiveInternalFns.count(Callee));
              },
              *F, true, nullptr, UsedAssumedInformation)) {
        continue;
      }

      LiveInternalFns.insert(F);
      F = nullptr;
      FoundLiveInternal = true;
    }
  }

  for (Function *F : InternalFns)
    if (F)
      ToBeDeletedFunctions.insert(F);
}

ChangeStatus Attributor::cleanupIR() {
  TimeTraceScope TimeScope("Attributor::cleanupIR");
  // Delete stuff at the end to avoid invalid references and a nice order.
  LLVM_DEBUG(dbgs() << "\n[Attributor] Delete/replace at least "
                    << ToBeDeletedFunctions.size() << " functions and "
                    << ToBeDeletedBlocks.size() << " blocks and "
                    << ToBeDeletedInsts.size() << " instructions and "
                    << ToBeChangedValues.size() << " values and "
                    << ToBeChangedUses.size() << " uses. To insert "
                    << ToBeChangedToUnreachableInsts.size()
                    << " unreachables.\n"
                    << "Preserve manifest added " << ManifestAddedBlocks.size()
                    << " blocks\n");

  SmallVector<WeakTrackingVH, 32> DeadInsts;
  SmallVector<Instruction *, 32> TerminatorsToFold;

  auto ReplaceUse = [&](Use *U, Value *NewV) {
    Value *OldV = U->get();

    // If we plan to replace NewV we need to update it at this point.
    do {
      const auto &Entry = ToBeChangedValues.lookup(NewV);
      if (!get<0>(Entry))
        break;
      NewV = get<0>(Entry);
    } while (true);

    Instruction *I = dyn_cast<Instruction>(U->getUser());
    assert((!I || isRunOn(*I->getFunction())) &&
           "Cannot replace an instruction outside the current SCC!");

    // Do not replace uses in returns if the value is a must-tail call we will
    // not delete.
    if (auto *RI = dyn_cast_or_null<ReturnInst>(I)) {
      if (auto *CI = dyn_cast<CallInst>(OldV->stripPointerCasts()))
        if (CI->isMustTailCall() && !ToBeDeletedInsts.count(CI))
          return;
      // If we rewrite a return and the new value is not an argument, strip the
      // `returned` attribute as it is wrong now.
      if (!isa<Argument>(NewV))
        for (auto &Arg : RI->getFunction()->args())
          Arg.removeAttr(Attribute::Returned);
    }

    LLVM_DEBUG(dbgs() << "Use " << *NewV << " in " << *U->getUser()
                      << " instead of " << *OldV << "\n");
    U->set(NewV);

    if (Instruction *I = dyn_cast<Instruction>(OldV)) {
      CGModifiedFunctions.insert(I->getFunction());
      if (!isa<PHINode>(I) && !ToBeDeletedInsts.count(I) &&
          isInstructionTriviallyDead(I))
        DeadInsts.push_back(I);
    }
    if (isa<UndefValue>(NewV) && isa<CallBase>(U->getUser())) {
      auto *CB = cast<CallBase>(U->getUser());
      if (CB->isArgOperand(U)) {
        unsigned Idx = CB->getArgOperandNo(U);
        CB->removeParamAttr(Idx, Attribute::NoUndef);
        auto *Callee = dyn_cast_if_present<Function>(CB->getCalledOperand());
        if (Callee && Callee->arg_size() > Idx)
          Callee->removeParamAttr(Idx, Attribute::NoUndef);
      }
    }
    if (isa<Constant>(NewV) && isa<CondBrInst>(U->getUser())) {
      Instruction *UserI = cast<Instruction>(U->getUser());
      if (isa<UndefValue>(NewV)) {
        ToBeChangedToUnreachableInsts.insert(UserI);
      } else {
        TerminatorsToFold.push_back(UserI);
      }
    }
  };

  for (auto &It : ToBeChangedUses) {
    Use *U = It.first;
    Value *NewV = It.second;
    ReplaceUse(U, NewV);
  }

  SmallVector<Use *, 4> Uses;
  for (auto &It : ToBeChangedValues) {
    Value *OldV = It.first;
    auto [NewV, Done] = It.second;
    Uses.clear();
    for (auto &U : OldV->uses())
      if (Done || !U.getUser()->isDroppable())
        Uses.push_back(&U);
    for (Use *U : Uses) {
      if (auto *I = dyn_cast<Instruction>(U->getUser()))
        if (!isRunOn(*I->getFunction()))
          continue;
      ReplaceUse(U, NewV);
    }
  }

  for (const auto &V : InvokeWithDeadSuccessor)
    if (InvokeInst *II = dyn_cast_or_null<InvokeInst>(V)) {
      assert(isRunOn(*II->getFunction()) &&
             "Cannot replace an invoke outside the current SCC!");
      bool UnwindBBIsDead = II->hasFnAttr(Attribute::NoUnwind);
      bool NormalBBIsDead = II->hasFnAttr(Attribute::NoReturn);
      bool Invoke2CallAllowed =
          !AAIsDead::mayCatchAsynchronousExceptions(*II->getFunction());
      assert((UnwindBBIsDead || NormalBBIsDead) &&
             "Invoke does not have dead successors!");
      BasicBlock *BB = II->getParent();
      BasicBlock *NormalDestBB = II->getNormalDest();
      if (UnwindBBIsDead) {
        Instruction *NormalNextIP = &NormalDestBB->front();
        if (Invoke2CallAllowed) {
          changeToCall(II);
          NormalNextIP = BB->getTerminator();
        }
        if (NormalBBIsDead)
          ToBeChangedToUnreachableInsts.insert(NormalNextIP);
      } else {
        assert(NormalBBIsDead && "Broken invariant!");
        if (!NormalDestBB->getUniquePredecessor())
          NormalDestBB = SplitBlockPredecessors(NormalDestBB, {BB}, ".dead");
        ToBeChangedToUnreachableInsts.insert(&NormalDestBB->front());
      }
    }
  for (Instruction *I : TerminatorsToFold) {
    assert(isRunOn(*I->getFunction()) &&
           "Cannot replace a terminator outside the current SCC!");
    CGModifiedFunctions.insert(I->getFunction());
    ConstantFoldTerminator(I->getParent());
  }
  for (const auto &V : ToBeChangedToUnreachableInsts)
    if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
      LLVM_DEBUG(dbgs() << "[Attributor] Change to unreachable: " << *I
                        << "\n");
      assert(isRunOn(*I->getFunction()) &&
             "Cannot replace an instruction outside the current SCC!");
      CGModifiedFunctions.insert(I->getFunction());
      changeToUnreachable(I);
    }

  for (const auto &V : ToBeDeletedInsts) {
    if (Instruction *I = dyn_cast_or_null<Instruction>(V)) {
      assert((!isa<CallBase>(I) || isa<IntrinsicInst>(I) ||
              isRunOn(*I->getFunction())) &&
             "Cannot delete an instruction outside the current SCC!");
      I->dropDroppableUses();
      CGModifiedFunctions.insert(I->getFunction());
      if (!I->getType()->isVoidTy())
        I->replaceAllUsesWith(UndefValue::get(I->getType()));
      if (!isa<PHINode>(I) && isInstructionTriviallyDead(I))
        DeadInsts.push_back(I);
      else
        I->eraseFromParent();
    }
  }

  llvm::erase_if(DeadInsts, [&](WeakTrackingVH I) { return !I; });

  LLVM_DEBUG({
    dbgs() << "[Attributor] DeadInsts size: " << DeadInsts.size() << "\n";
    for (auto &I : DeadInsts)
      if (I)
        dbgs() << "  - " << *I << "\n";
  });

  RecursivelyDeleteTriviallyDeadInstructions(DeadInsts);

  if (unsigned NumDeadBlocks = ToBeDeletedBlocks.size()) {
    SmallVector<BasicBlock *, 8> ToBeDeletedBBs;
    ToBeDeletedBBs.reserve(NumDeadBlocks);
    for (BasicBlock *BB : ToBeDeletedBlocks) {
      assert(isRunOn(*BB->getParent()) &&
             "Cannot delete a block outside the current SCC!");
      CGModifiedFunctions.insert(BB->getParent());
      // Do not delete BBs added during manifests of AAs.
      if (ManifestAddedBlocks.contains(BB))
        continue;
      ToBeDeletedBBs.push_back(BB);
    }
    // Actually we do not delete the blocks but squash them into a single
    // unreachable but untangling branches that jump here is something we need
    // to do in a more generic way.
    detachDeadBlocks(ToBeDeletedBBs, nullptr);
  }

  identifyDeadInternalFunctions();

  // Rewrite the functions as requested during manifest.
  ChangeStatus ManifestChange = rewriteFunctionSignatures(CGModifiedFunctions);

  for (Function *Fn : CGModifiedFunctions)
    if (!ToBeDeletedFunctions.count(Fn) && Functions.count(Fn))
      Configuration.CGUpdater.reanalyzeFunction(*Fn);

  for (Function *Fn : ToBeDeletedFunctions) {
    if (!Functions.count(Fn))
      continue;
    Configuration.CGUpdater.removeFunction(*Fn);
  }

  if (!ToBeChangedUses.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!ToBeChangedToUnreachableInsts.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!ToBeDeletedFunctions.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!ToBeDeletedBlocks.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!ToBeDeletedInsts.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!InvokeWithDeadSuccessor.empty())
    ManifestChange = ChangeStatus::CHANGED;

  if (!DeadInsts.empty())
    ManifestChange = ChangeStatus::CHANGED;

  NumFnDeleted += ToBeDeletedFunctions.size();

  LLVM_DEBUG(dbgs() << "[Attributor] Deleted " << ToBeDeletedFunctions.size()
                    << " functions after manifest.\n");

#ifdef EXPENSIVE_CHECKS
  for (Function *F : Functions) {
    if (ToBeDeletedFunctions.count(F))
      continue;
    assert(!verifyFunction(*F, &errs()) && "Module verification failed!");
  }
#endif

  return ManifestChange;
}

ChangeStatus Attributor::run() {
  TimeTraceScope TimeScope("Attributor::run");
  AttributorCallGraph ACallGraph(*this);

  if (PrintCallGraph)
    ACallGraph.populateAll();

  Phase = AttributorPhase::UPDATE;
  runTillFixpoint();

  // dump graphs on demand
  if (DumpDepGraph)
    DG.dumpGraph();

  if (ViewDepGraph)
    DG.viewGraph();

  if (PrintDependencies)
    DG.print();

  Phase = AttributorPhase::MANIFEST;
  ChangeStatus ManifestChange = manifestAttributes();

  Phase = AttributorPhase::CLEANUP;
  ChangeStatus CleanupChange = cleanupIR();

  if (PrintCallGraph)
    ACallGraph.print();

  return ManifestChange | CleanupChange;
}

ChangeStatus Attributor::updateAA(AbstractAttribute &AA) {
  TimeTraceScope TimeScope("updateAA", [&]() {
    return AA.getName().str() +
           std::to_string(AA.getIRPosition().getPositionKind());
  });
  assert(Phase == AttributorPhase::UPDATE &&
         "We can update AA only in the update stage!");

  // Use a new dependence vector for this update.
  DependenceVector DV;
  DependenceStack.push_back(&DV);

  auto &AAState = AA.getState();
  ChangeStatus CS = ChangeStatus::UNCHANGED;
  bool UsedAssumedInformation = false;
  if (!isAssumedDead(AA, nullptr, UsedAssumedInformation,
                     /* CheckBBLivenessOnly */ true))
    CS = AA.update(*this);

  if (!AA.isQueryAA() && DV.empty() && !AA.getState().isAtFixpoint()) {
    // If the AA did not rely on outside information but changed, we run it
    // again to see if it found a fixpoint. Most AAs do but we don't require
    // them to. Hence, it might take the AA multiple iterations to get to a
    // fixpoint even if it does not rely on outside information, which is fine.
    ChangeStatus RerunCS = ChangeStatus::UNCHANGED;
    if (CS == ChangeStatus::CHANGED)
      RerunCS = AA.update(*this);

    // If the attribute did not change during the run or rerun, and it still did
    // not query any non-fix information, the state will not change and we can
    // indicate that right at this point.
    if (RerunCS == ChangeStatus::UNCHANGED && !AA.isQueryAA() && DV.empty())
      AAState.indicateOptimisticFixpoint();
  }

  if (!AAState.isAtFixpoint())
    rememberDependences();

  // Verify the stack was used properly, that is we pop the dependence vector we
  // put there earlier.
  DependenceVector *PoppedDV = DependenceStack.pop_back_val();
  (void)PoppedDV;
  assert(PoppedDV == &DV && "Inconsistent usage of the dependence stack!");

  return CS;
}

void Attributor::createShallowWrapper(Function &F) {
  assert(!F.isDeclaration() && "Cannot create a wrapper around a declaration!");

  Module &M = *F.getParent();
  LLVMContext &Ctx = M.getContext();
  FunctionType *FnTy = F.getFunctionType();

  Function *Wrapper =
      Function::Create(FnTy, F.getLinkage(), F.getAddressSpace(), F.getName());
  F.setName(""); // set the inside function anonymous
  M.getFunctionList().insert(F.getIterator(), Wrapper);

  F.setLinkage(GlobalValue::InternalLinkage);

  F.replaceAllUsesWith(Wrapper);
  assert(F.use_empty() && "Uses remained after wrapper was created!");

  // Move the COMDAT section to the wrapper.
  // TODO: Check if we need to keep it for F as well.
  Wrapper->setComdat(F.getComdat());
  F.setComdat(nullptr);

  // Copy all metadata and attributes but keep them on F as well.
  SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
  F.getAllMetadata(MDs);
  for (auto MDIt : MDs)
    Wrapper->addMetadata(MDIt.first, *MDIt.second);
  Wrapper->setAttributes(F.getAttributes());

  // Create the call in the wrapper.
  BasicBlock *EntryBB = BasicBlock::Create(Ctx, "entry", Wrapper);

  SmallVector<Value *, 8> Args;
  Argument *FArgIt = F.arg_begin();
  for (Argument &Arg : Wrapper->args()) {
    Args.push_back(&Arg);
    Arg.setName((FArgIt++)->getName());
  }

  CallInst *CI = CallInst::Create(&F, Args, "", EntryBB);
  CI->setTailCall(true);
  CI->addFnAttr(Attribute::NoInline);
  ReturnInst::Create(Ctx, CI->getType()->isVoidTy() ? nullptr : CI, EntryBB);

  NumFnShallowWrappersCreated++;
}

bool Attributor::isInternalizable(Function &F) {
  if (F.isDeclaration() || F.hasLocalLinkage() ||
      GlobalValue::isInterposableLinkage(F.getLinkage()))
    return false;
  return true;
}

Function *Attributor::internalizeFunction(Function &F, bool Force) {
  if (!AllowDeepWrapper && !Force)
    return nullptr;
  if (!isInternalizable(F))
    return nullptr;

  SmallPtrSet<Function *, 2> FnSet = {&F};
  DenseMap<Function *, Function *> InternalizedFns;
  internalizeFunctions(FnSet, InternalizedFns);

  return InternalizedFns[&F];
}

bool Attributor::internalizeFunctions(SmallPtrSetImpl<Function *> &FnSet,
                                      DenseMap<Function *, Function *> &FnMap) {
  for (Function *F : FnSet)
    if (!Attributor::isInternalizable(*F))
      return false;

  FnMap.clear();
  // Generate the internalized version of each function.
  for (Function *F : FnSet) {
    Module &M = *F->getParent();
    FunctionType *FnTy = F->getFunctionType();

    // Create a copy of the current function
    Function *Copied =
        Function::Create(FnTy, F->getLinkage(), F->getAddressSpace(),
                         F->getName() + ".internalized");
    ValueToValueMapTy VMap;
    auto *NewFArgIt = Copied->arg_begin();
    for (auto &Arg : F->args()) {
      auto ArgName = Arg.getName();
      NewFArgIt->setName(ArgName);
      VMap[&Arg] = &(*NewFArgIt++);
    }
    SmallVector<ReturnInst *, 8> Returns;

    // Copy the body of the original function to the new one
    CloneFunctionInto(Copied, F, VMap,
                      CloneFunctionChangeType::LocalChangesOnly, Returns);

    // Set the linakage and visibility late as CloneFunctionInto has some
    // implicit requirements.
    Copied->setVisibility(GlobalValue::DefaultVisibility);
    Copied->setLinkage(GlobalValue::PrivateLinkage);

    // Copy metadata
    SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
    F->getAllMetadata(MDs);
    for (auto MDIt : MDs)
      if (!Copied->hasMetadata())
        Copied->addMetadata(MDIt.first, *MDIt.second);

    M.getFunctionList().insert(F->getIterator(), Copied);
    Copied->setDSOLocal(true);
    FnMap[F] = Copied;
  }

  // Replace all uses of the old function with the new internalized function
  // unless the caller is a function that was just internalized.
  for (Function *F : FnSet) {
    auto &InternalizedFn = FnMap[F];
    auto IsNotInternalized = [&](Use &U) -> bool {
      if (auto *CB = dyn_cast<CallBase>(U.getUser()))
        return !FnMap.lookup(CB->getCaller());
      return false;
    };
    F->replaceUsesWithIf(InternalizedFn, IsNotInternalized);
  }

  return true;
}

bool Attributor::isValidFunctionSignatureRewrite(
    Argument &Arg, ArrayRef<Type *> ReplacementTypes) {

  if (!Configuration.RewriteSignatures)
    return false;

  Function *Fn = Arg.getParent();
  auto CallSiteCanBeChanged = [Fn](AbstractCallSite ACS) {
    // Forbid the call site to cast the function return type. If we need to
    // rewrite these functions we need to re-create a cast for the new call site
    // (if the old had uses).
    if (!ACS.getCalledFunction() ||
        ACS.getInstruction()->getType() !=
            ACS.getCalledFunction()->getReturnType())
      return false;
    if (cast<CallBase>(ACS.getInstruction())->getCalledOperand()->getType() !=
        Fn->getType())
      return false;
    if (ACS.getNumArgOperands() != Fn->arg_size())
      return false;
    // Forbid must-tail calls for now.
    return !ACS.isCallbackCall() && !ACS.getInstruction()->isMustTailCall();
  };

  // Avoid var-arg functions for now.
  if (Fn->isVarArg()) {
    LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite var-args functions\n");
    return false;
  }

  // Avoid functions with complicated argument passing semantics.
  AttributeList FnAttributeList = Fn->getAttributes();
  if (FnAttributeList.hasAttrSomewhere(Attribute::Nest) ||
      FnAttributeList.hasAttrSomewhere(Attribute::StructRet) ||
      FnAttributeList.hasAttrSomewhere(Attribute::InAlloca) ||
      FnAttributeList.hasAttrSomewhere(Attribute::Preallocated)) {
    LLVM_DEBUG(
        dbgs() << "[Attributor] Cannot rewrite due to complex attribute\n");
    return false;
  }

  // Avoid callbacks for now.
  bool UsedAssumedInformation = false;
  if (!checkForAllCallSites(CallSiteCanBeChanged, *Fn, true, nullptr,
                            UsedAssumedInformation,
                            /* CheckPotentiallyDead */ true)) {
    LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite all call sites\n");
    return false;
  }

  auto InstPred = [](Instruction &I) {
    if (auto *CI = dyn_cast<CallInst>(&I))
      return !CI->isMustTailCall();
    return true;
  };

  // Forbid must-tail calls for now.
  // TODO:
  auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(*Fn);
  if (!checkForAllInstructionsImpl(nullptr, OpcodeInstMap, InstPred, nullptr,
                                   nullptr, {Instruction::Call},
                                   UsedAssumedInformation)) {
    LLVM_DEBUG(dbgs() << "[Attributor] Cannot rewrite due to instructions\n");
    return false;
  }

  return true;
}

bool Attributor::registerFunctionSignatureRewrite(
    Argument &Arg, ArrayRef<Type *> ReplacementTypes,
    ArgumentReplacementInfo::CalleeRepairCBTy &&CalleeRepairCB,
    ArgumentReplacementInfo::ACSRepairCBTy &&ACSRepairCB) {
  LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "
                    << Arg.getParent()->getName() << " with "
                    << ReplacementTypes.size() << " replacements\n");
  assert(isValidFunctionSignatureRewrite(Arg, ReplacementTypes) &&
         "Cannot register an invalid rewrite");

  Function *Fn = Arg.getParent();
  SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
      ArgumentReplacementMap[Fn];
  if (ARIs.empty())
    ARIs.resize(Fn->arg_size());

  // If we have a replacement already with less than or equal new arguments,
  // ignore this request.
  std::unique_ptr<ArgumentReplacementInfo> &ARI = ARIs[Arg.getArgNo()];
  if (ARI && ARI->getNumReplacementArgs() <= ReplacementTypes.size()) {
    LLVM_DEBUG(dbgs() << "[Attributor] Existing rewrite is preferred\n");
    return false;
  }

  // If we have a replacement already but we like the new one better, delete
  // the old.
  ARI.reset();

  LLVM_DEBUG(dbgs() << "[Attributor] Register new rewrite of " << Arg << " in "
                    << Arg.getParent()->getName() << " with "
                    << ReplacementTypes.size() << " replacements\n");

  // Remember the replacement.
  ARI.reset(new ArgumentReplacementInfo(*this, Arg, ReplacementTypes,
                                        std::move(CalleeRepairCB),
                                        std::move(ACSRepairCB)));

  return true;
}

bool Attributor::shouldSeedAttribute(AbstractAttribute &AA) {
  bool Result = true;
#ifndef NDEBUG
  if (SeedAllowList.size() != 0)
    Result = llvm::is_contained(SeedAllowList, AA.getName());
  Function *Fn = AA.getAnchorScope();
  if (FunctionSeedAllowList.size() != 0 && Fn)
    Result &= llvm::is_contained(FunctionSeedAllowList, Fn->getName());
#endif
  return Result;
}

ChangeStatus Attributor::rewriteFunctionSignatures(
    SmallSetVector<Function *, 8> &ModifiedFns) {
  ChangeStatus Changed = ChangeStatus::UNCHANGED;

  for (auto &It : ArgumentReplacementMap) {
    Function *OldFn = It.getFirst();

    // Deleted functions do not require rewrites.
    if (!Functions.count(OldFn) || ToBeDeletedFunctions.count(OldFn))
      continue;

    const SmallVectorImpl<std::unique_ptr<ArgumentReplacementInfo>> &ARIs =
        It.getSecond();
    assert(ARIs.size() == OldFn->arg_size() && "Inconsistent state!");

    SmallVector<Type *, 16> NewArgumentTypes;
    SmallVector<AttributeSet, 16> NewArgumentAttributes;

    // Collect replacement argument types and copy over existing attributes.
    AttributeList OldFnAttributeList = OldFn->getAttributes();
    for (Argument &Arg : OldFn->args()) {
      if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
              ARIs[Arg.getArgNo()]) {
        NewArgumentTypes.append(ARI->ReplacementTypes.begin(),
                                ARI->ReplacementTypes.end());
        NewArgumentAttributes.append(ARI->getNumReplacementArgs(),
                                     AttributeSet());
      } else {
        NewArgumentTypes.push_back(Arg.getType());
        NewArgumentAttributes.push_back(
            OldFnAttributeList.getParamAttrs(Arg.getArgNo()));
      }
    }

    uint64_t LargestVectorWidth = 0;
    for (auto *I : NewArgumentTypes)
      if (auto *VT = dyn_cast<llvm::VectorType>(I))
        LargestVectorWidth =
            std::max(LargestVectorWidth,
                     VT->getPrimitiveSizeInBits().getKnownMinValue());

    FunctionType *OldFnTy = OldFn->getFunctionType();
    Type *RetTy = OldFnTy->getReturnType();

    // Construct the new function type using the new arguments types.
    FunctionType *NewFnTy =
        FunctionType::get(RetTy, NewArgumentTypes, OldFnTy->isVarArg());

    LLVM_DEBUG(dbgs() << "[Attributor] Function rewrite '" << OldFn->getName()
                      << "' from " << *OldFn->getFunctionType() << " to "
                      << *NewFnTy << "\n");

    // Create the new function body and insert it into the module.
    Function *NewFn = Function::Create(NewFnTy, OldFn->getLinkage(),
                                       OldFn->getAddressSpace(), "");
    Functions.insert(NewFn);
    OldFn->getParent()->getFunctionList().insert(OldFn->getIterator(), NewFn);
    NewFn->takeName(OldFn);
    NewFn->copyAttributesFrom(OldFn);

    // Patch the pointer to LLVM function in debug info descriptor.
    NewFn->setSubprogram(OldFn->getSubprogram());
    OldFn->setSubprogram(nullptr);

    // Recompute the parameter attributes list based on the new arguments for
    // the function.
    LLVMContext &Ctx = OldFn->getContext();
    NewFn->setAttributes(AttributeList::get(
        Ctx, OldFnAttributeList.getFnAttrs(), OldFnAttributeList.getRetAttrs(),
        NewArgumentAttributes));
    AttributeFuncs::updateMinLegalVectorWidthAttr(*NewFn, LargestVectorWidth);

    // Remove argmem from the memory effects if we have no more pointer
    // arguments, or they are readnone.
    MemoryEffects ME = NewFn->getMemoryEffects();
    int ArgNo = -1;
    if (ME.doesAccessArgPointees() && all_of(NewArgumentTypes, [&](Type *T) {
          ++ArgNo;
          return !T->isPtrOrPtrVectorTy() ||
                 NewFn->hasParamAttribute(ArgNo, Attribute::ReadNone);
        })) {
      NewFn->setMemoryEffects(ME - MemoryEffects::argMemOnly());
    }

    // Since we have now created the new function, splice the body of the old
    // function right into the new function, leaving the old rotting hulk of the
    // function empty.
    NewFn->splice(NewFn->begin(), OldFn);

    // Set of all "call-like" instructions that invoke the old function mapped
    // to their new replacements.
    SmallVector<std::pair<CallBase *, CallBase *>, 8> CallSitePairs;

    // Callback to create a new "call-like" instruction for a given one.
    auto CallSiteReplacementCreator = [&](AbstractCallSite ACS) {
      CallBase *OldCB = cast<CallBase>(ACS.getInstruction());
      const AttributeList &OldCallAttributeList = OldCB->getAttributes();

      // Collect the new argument operands for the replacement call site.
      SmallVector<Value *, 16> NewArgOperands;
      SmallVector<AttributeSet, 16> NewArgOperandAttributes;
      for (unsigned OldArgNum = 0; OldArgNum < ARIs.size(); ++OldArgNum) {
        unsigned NewFirstArgNum = NewArgOperands.size();
        (void)NewFirstArgNum; // only used inside assert.
        if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
                ARIs[OldArgNum]) {
          if (ARI->ACSRepairCB)
            ARI->ACSRepairCB(*ARI, ACS, NewArgOperands);
          assert(ARI->getNumReplacementArgs() + NewFirstArgNum ==
                     NewArgOperands.size() &&
                 "ACS repair callback did not provide as many operand as new "
                 "types were registered!");
          // TODO: Exose the attribute set to the ACS repair callback
          NewArgOperandAttributes.append(ARI->ReplacementTypes.size(),
                                         AttributeSet());
        } else {
          NewArgOperands.push_back(ACS.getCallArgOperand(OldArgNum));
          NewArgOperandAttributes.push_back(
              OldCallAttributeList.getParamAttrs(OldArgNum));
        }
      }

      assert(NewArgOperands.size() == NewArgOperandAttributes.size() &&
             "Mismatch # argument operands vs. # argument operand attributes!");
      assert(NewArgOperands.size() == NewFn->arg_size() &&
             "Mismatch # argument operands vs. # function arguments!");

      SmallVector<OperandBundleDef, 4> OperandBundleDefs;
      OldCB->getOperandBundlesAsDefs(OperandBundleDefs);

      // Create a new call or invoke instruction to replace the old one.
      CallBase *NewCB;
      if (InvokeInst *II = dyn_cast<InvokeInst>(OldCB)) {
        NewCB = InvokeInst::Create(NewFn, II->getNormalDest(),
                                   II->getUnwindDest(), NewArgOperands,
                                   OperandBundleDefs, "", OldCB->getIterator());
      } else {
        auto *NewCI = CallInst::Create(NewFn, NewArgOperands, OperandBundleDefs,
                                       "", OldCB->getIterator());
        NewCI->setTailCallKind(cast<CallInst>(OldCB)->getTailCallKind());
        NewCB = NewCI;
      }

      // Copy over various properties and the new attributes.
      NewCB->copyMetadata(*OldCB, {LLVMContext::MD_prof, LLVMContext::MD_dbg});
      NewCB->setCallingConv(OldCB->getCallingConv());
      NewCB->takeName(OldCB);
      NewCB->setAttributes(AttributeList::get(
          Ctx, OldCallAttributeList.getFnAttrs(),
          OldCallAttributeList.getRetAttrs(), NewArgOperandAttributes));

      AttributeFuncs::updateMinLegalVectorWidthAttr(*NewCB->getCaller(),
                                                    LargestVectorWidth);

      CallSitePairs.push_back({OldCB, NewCB});
      return true;
    };

    // Use the CallSiteReplacementCreator to create replacement call sites.
    bool UsedAssumedInformation = false;
    bool Success = checkForAllCallSites(CallSiteReplacementCreator, *OldFn,
                                        true, nullptr, UsedAssumedInformation,
                                        /* CheckPotentiallyDead */ true);
    (void)Success;
    assert(Success && "Assumed call site replacement to succeed!");

    // Rewire the arguments.
    Argument *OldFnArgIt = OldFn->arg_begin();
    Argument *NewFnArgIt = NewFn->arg_begin();
    for (unsigned OldArgNum = 0; OldArgNum < ARIs.size();
         ++OldArgNum, ++OldFnArgIt) {
      if (const std::unique_ptr<ArgumentReplacementInfo> &ARI =
              ARIs[OldArgNum]) {
        if (ARI->CalleeRepairCB)
          ARI->CalleeRepairCB(*ARI, *NewFn, NewFnArgIt);
        if (ARI->ReplacementTypes.empty())
          OldFnArgIt->replaceAllUsesWith(
              PoisonValue::get(OldFnArgIt->getType()));
        NewFnArgIt += ARI->ReplacementTypes.size();
      } else {
        NewFnArgIt->takeName(&*OldFnArgIt);
        OldFnArgIt->replaceAllUsesWith(&*NewFnArgIt);
        ++NewFnArgIt;
      }
    }

    // Eliminate the instructions *after* we visited all of them.
    for (auto &CallSitePair : CallSitePairs) {
      CallBase &OldCB = *CallSitePair.first;
      CallBase &NewCB = *CallSitePair.second;
      assert(OldCB.getType() == NewCB.getType() &&
             "Cannot handle call sites with different types!");
      ModifiedFns.insert(OldCB.getFunction());
      OldCB.replaceAllUsesWith(&NewCB);
      OldCB.eraseFromParent();
    }

    // Replace the function in the call graph (if any).
    Configuration.CGUpdater.replaceFunctionWith(*OldFn, *NewFn);

    // If the old function was modified and needed to be reanalyzed, the new one
    // does now.
    if (ModifiedFns.remove(OldFn))
      ModifiedFns.insert(NewFn);

    Changed = ChangeStatus::CHANGED;
  }

  return Changed;
}

void InformationCache::initializeInformationCache(const Function &CF,
                                                  FunctionInfo &FI) {
  // As we do not modify the function here we can remove the const
  // withouth breaking implicit assumptions. At the end of the day, we could
  // initialize the cache eagerly which would look the same to the users.
  Function &F = const_cast<Function &>(CF);

  FI.IsKernel = F.hasFnAttribute("kernel");

  // Walk all instructions to find interesting instructions that might be
  // queried by abstract attributes during their initialization or update.
  // This has to happen before we create attributes.

  DenseMap<const Value *, std::optional<short>> AssumeUsesMap;

  // Add \p V to the assume uses map which track the number of uses outside of
  // "visited" assumes. If no outside uses are left the value is added to the
  // assume only use vector.
  auto AddToAssumeUsesMap = [&](const Value &V) -> void {
    SmallVector<const Instruction *> Worklist;
    if (auto *I = dyn_cast<Instruction>(&V))
      Worklist.push_back(I);
    while (!Worklist.empty()) {
      const Instruction *I = Worklist.pop_back_val();
      std::optional<short> &NumUses = AssumeUsesMap[I];
      if (!NumUses)
        NumUses = I->getNumUses();
      NumUses = *NumUses - /* this assume */ 1;
      if (*NumUses != 0)
        continue;
      AssumeOnlyValues.insert(I);
      for (const Value *Op : I->operands())
        if (auto *OpI = dyn_cast<Instruction>(Op))
          Worklist.push_back(OpI);
    }
  };

  for (Instruction &I : instructions(&F)) {
    bool IsInterestingOpcode = false;

    // To allow easy access to all instructions in a function with a given
    // opcode we store them in the InfoCache. As not all opcodes are interesting
    // to concrete attributes we only cache the ones that are as identified in
    // the following switch.
    // Note: There are no concrete attributes now so this is initially empty.
    switch (I.getOpcode()) {
    default:
      assert(!isa<CallBase>(&I) &&
             "New call base instruction type needs to be known in the "
             "Attributor.");
      break;
    case Instruction::Call:
      // Calls are interesting on their own, additionally:
      // For `llvm.assume` calls we also fill the KnowledgeMap as we find them.
      // For `must-tail` calls we remember the caller and callee.
      if (auto *Assume = dyn_cast<AssumeInst>(&I)) {
        AssumeOnlyValues.insert(Assume);
        fillMapFromAssume(*Assume, KnowledgeMap);
        AddToAssumeUsesMap(*Assume->getArgOperand(0));
      } else if (cast<CallInst>(I).isMustTailCall()) {
        FI.ContainsMustTailCall = true;
        if (auto *Callee = dyn_cast_if_present<Function>(
                cast<CallInst>(I).getCalledOperand()))
          getFunctionInfo(*Callee).CalledViaMustTail = true;
      }
      [[fallthrough]];
    case Instruction::CallBr:
    case Instruction::Invoke:
    case Instruction::CleanupRet:
    case Instruction::CatchSwitch:
    case Instruction::AtomicRMW:
    case Instruction::AtomicCmpXchg:
    case Instruction::UncondBr:
    case Instruction::CondBr:
    case Instruction::Resume:
    case Instruction::Ret:
    case Instruction::Load:
      // The alignment of a pointer is interesting for loads.
    case Instruction::Store:
      // The alignment of a pointer is interesting for stores.
    case Instruction::Alloca:
    case Instruction::AddrSpaceCast:
      IsInterestingOpcode = true;
    }
    if (IsInterestingOpcode) {
      auto *&Insts = FI.OpcodeInstMap[I.getOpcode()];
      if (!Insts)
        Insts = new (Allocator) InstructionVectorTy();
      Insts->push_back(&I);
    }
    if (I.mayReadOrWriteMemory())
      FI.RWInsts.push_back(&I);
  }

  if (F.hasFnAttribute(Attribute::AlwaysInline) &&
      isInlineViable(F).isSuccess())
    InlineableFunctions.insert(&F);
}

InformationCache::FunctionInfo::~FunctionInfo() {
  // The instruction vectors are allocated using a BumpPtrAllocator, we need to
  // manually destroy them.
  for (auto &It : OpcodeInstMap)
    It.getSecond()->~InstructionVectorTy();
}

ArrayRef<Function *>
InformationCache::getIndirectlyCallableFunctions(Attributor &A) const {
  assert(A.isClosedWorldModule() && "Cannot see all indirect callees!");
  return IndirectlyCallableFunctions;
}

std::optional<unsigned> InformationCache::getFlatAddressSpace() const {
  if (IsTargetGPU())
    return 0;
  return std::nullopt;
}

void Attributor::recordDependence(const AbstractAttribute &FromAA,
                                  const AbstractAttribute &ToAA,
                                  DepClassTy DepClass) {
  if (DepClass == DepClassTy::NONE)
    return;
  // If we are outside of an update, thus before the actual fixpoint iteration
  // started (= when we create AAs), we do not track dependences because we will
  // put all AAs into the initial worklist anyway.
  if (DependenceStack.empty())
    return;
  if (FromAA.getState().isAtFixpoint())
    return;
  DependenceStack.back()->push_back({&FromAA, &ToAA, DepClass});
}

void Attributor::rememberDependences() {
  assert(!DependenceStack.empty() && "No dependences to remember!");

  for (DepInfo &DI : *DependenceStack.back()) {
    assert((DI.DepClass == DepClassTy::REQUIRED ||
            DI.DepClass == DepClassTy::OPTIONAL) &&
           "Expected required or optional dependence (1 bit)!");
    auto &DepAAs = const_cast<AbstractAttribute &>(*DI.FromAA).Deps;
    DepAAs.insert(AbstractAttribute::DepTy(
        const_cast<AbstractAttribute *>(DI.ToAA), unsigned(DI.DepClass)));
  }
}

template <Attribute::AttrKind AK, typename AAType>
void Attributor::checkAndQueryIRAttr(const IRPosition &IRP, AttributeSet Attrs,
                                     bool SkipHasAttrCheck) {
  bool IsKnown;
  if (SkipHasAttrCheck || !Attrs.hasAttribute(AK))
    if (!Configuration.Allowed || Configuration.Allowed->count(&AAType::ID))
      if (!AA::hasAssumedIRAttr<AK>(*this, nullptr, IRP, DepClassTy::NONE,
                                    IsKnown))
        getOrCreateAAFor<AAType>(IRP);
}

void Attributor::identifyDefaultAbstractAttributes(Function &F) {
  assert(!F.isDeclaration());

  if (!VisitedFunctions.insert(&F).second)
    return;

  // In non-module runs we need to look at the call sites of a function to
  // determine if it is part of a must-tail call edge. This will influence what
  // attributes we can derive.
  InformationCache::FunctionInfo &FI = InfoCache.getFunctionInfo(F);
  if (!isModulePass() && !FI.CalledViaMustTail) {
    for (const Use &U : F.uses())
      if (const auto *CB = dyn_cast<CallBase>(U.getUser()))
        if (CB->isCallee(&U) && CB->isMustTailCall())
          FI.CalledViaMustTail = true;
  }

  IRPosition FPos = IRPosition::function(F);
  bool IsIPOAmendable = isFunctionIPOAmendable(F);
  auto Attrs = F.getAttributes();
  auto FnAttrs = Attrs.getFnAttrs();

  // Check for dead BasicBlocks in every function.
  // We need dead instruction detection because we do not want to deal with
  // broken IR in which SSA rules do not apply.
  getOrCreateAAFor<AAIsDead>(FPos);

  // Every function might contain instructions that cause "undefined
  // behavior".
  getOrCreateAAFor<AAUndefinedBehavior>(FPos);

  // Every function might be applicable for Heap-To-Stack conversion.
  if (EnableHeapToStack)
    getOrCreateAAFor<AAHeapToStack>(FPos);

  // Every function might be "must-progress".
  checkAndQueryIRAttr<Attribute::MustProgress, AAMustProgress>(FPos, FnAttrs);

  // Every function might be "no-free".
  checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(FPos, FnAttrs);

  // Every function might be "will-return".
  checkAndQueryIRAttr<Attribute::WillReturn, AAWillReturn>(FPos, FnAttrs);

  // Every function might be marked "nosync"
  checkAndQueryIRAttr<Attribute::NoSync, AANoSync>(FPos, FnAttrs);

  // Everything that is visible from the outside (=function, argument, return
  // positions), cannot be changed if the function is not IPO amendable. We can
  // however analyse the code inside.
  if (IsIPOAmendable) {

    // Every function can be nounwind.
    checkAndQueryIRAttr<Attribute::NoUnwind, AANoUnwind>(FPos, FnAttrs);

    // Every function might be "no-return".
    checkAndQueryIRAttr<Attribute::NoReturn, AANoReturn>(FPos, FnAttrs);

    // Every function might be "no-recurse".
    checkAndQueryIRAttr<Attribute::NoRecurse, AANoRecurse>(FPos, FnAttrs);

    // Every function can be "non-convergent".
    if (Attrs.hasFnAttr(Attribute::Convergent))
      getOrCreateAAFor<AANonConvergent>(FPos);

    // Every function might be "readnone/readonly/writeonly/...".
    getOrCreateAAFor<AAMemoryBehavior>(FPos);

    // Every function can be "readnone/argmemonly/inaccessiblememonly/...".
    getOrCreateAAFor<AAMemoryLocation>(FPos);

    // Every function can track active assumptions.
    getOrCreateAAFor<AAAssumptionInfo>(FPos);

    // If we're not using a dynamic mode for float, there's nothing worthwhile
    // to infer. This misses the edge case denormal-fp-math="dynamic" and
    // denormal-fp-math-f32=something, but that likely has no real world use.
    DenormalMode Mode = F.getDenormalMode(APFloat::IEEEsingle());
    if (Mode.Input == DenormalMode::Dynamic ||
        Mode.Output == DenormalMode::Dynamic)
      getOrCreateAAFor<AADenormalFPMath>(FPos);

    // Return attributes are only appropriate if the return type is non void.
    Type *ReturnType = F.getReturnType();
    if (!ReturnType->isVoidTy()) {
      IRPosition RetPos = IRPosition::returned(F);
      AttributeSet RetAttrs = Attrs.getRetAttrs();

      // Every returned value might be dead.
      getOrCreateAAFor<AAIsDead>(RetPos);

      // Every function might be simplified.
      bool UsedAssumedInformation = false;
      getAssumedSimplified(RetPos, nullptr, UsedAssumedInformation,
                           AA::Intraprocedural);

      // Every returned value might be marked noundef.
      checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(RetPos, RetAttrs);

      if (ReturnType->isPointerTy()) {

        // Every function with pointer return type might be marked align.
        getOrCreateAAFor<AAAlign>(RetPos);

        // Every function with pointer return type might be marked nonnull.
        checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(RetPos, RetAttrs);

        // Every function with pointer return type might be marked noalias.
        checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(RetPos, RetAttrs);

        // Every function with pointer return type might be marked
        // dereferenceable.
        getOrCreateAAFor<AADereferenceable>(RetPos);
      } else if (AttributeFuncs::isNoFPClassCompatibleType(ReturnType)) {
        getOrCreateAAFor<AANoFPClass>(RetPos);
      }
    }
  }

  for (Argument &Arg : F.args()) {
    IRPosition ArgPos = IRPosition::argument(Arg);
    auto ArgNo = Arg.getArgNo();
    AttributeSet ArgAttrs = Attrs.getParamAttrs(ArgNo);

    if (!IsIPOAmendable) {
      if (Arg.getType()->isPointerTy())
        // Every argument with pointer type might be marked nofree.
        checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);
      continue;
    }

    // Every argument might be simplified. We have to go through the
    // Attributor interface though as outside AAs can register custom
    // simplification callbacks.
    bool UsedAssumedInformation = false;
    getAssumedSimplified(ArgPos, /* AA */ nullptr, UsedAssumedInformation,
                         AA::Intraprocedural);

    // Every argument might be dead.
    getOrCreateAAFor<AAIsDead>(ArgPos);

    // Every argument might be marked noundef.
    checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(ArgPos, ArgAttrs);

    if (Arg.getType()->isPointerTy()) {
      // Every argument with pointer type might be marked nonnull.
      checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(ArgPos, ArgAttrs);

      // Every argument with pointer type might be marked noalias.
      checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(ArgPos, ArgAttrs);

      // Every argument with pointer type might be marked dereferenceable.
      getOrCreateAAFor<AADereferenceable>(ArgPos);

      // Every argument with pointer type might be marked align.
      getOrCreateAAFor<AAAlign>(ArgPos);

      // Every argument with pointer type might be marked nocapture.
      checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
          ArgPos, ArgAttrs, /*SkipHasAttrCheck=*/true);

      // Every argument with pointer type might be marked
      // "readnone/readonly/writeonly/..."
      getOrCreateAAFor<AAMemoryBehavior>(ArgPos);

      // Every argument with pointer type might be marked nofree.
      checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(ArgPos, ArgAttrs);

      // Every argument with pointer type might be privatizable (or
      // promotable)
      getOrCreateAAFor<AAPrivatizablePtr>(ArgPos);
    } else if (AttributeFuncs::isNoFPClassCompatibleType(Arg.getType())) {
      getOrCreateAAFor<AANoFPClass>(ArgPos);
    }
  }

  auto CallSitePred = [&](Instruction &I) -> bool {
    auto &CB = cast<CallBase>(I);
    IRPosition CBInstPos = IRPosition::inst(CB);
    IRPosition CBFnPos = IRPosition::callsite_function(CB);

    // Call sites might be dead if they do not have side effects and no live
    // users. The return value might be dead if there are no live users.
    getOrCreateAAFor<AAIsDead>(CBInstPos);

    Function *Callee = dyn_cast_if_present<Function>(CB.getCalledOperand());
    // TODO: Even if the callee is not known now we might be able to simplify
    //       the call/callee.
    if (!Callee) {
      getOrCreateAAFor<AAIndirectCallInfo>(CBFnPos);
      return true;
    }

    // Every call site can track active assumptions.
    getOrCreateAAFor<AAAssumptionInfo>(CBFnPos);

    // Skip declarations except if annotations on their call sites were
    // explicitly requested.
    if (!AnnotateDeclarationCallSites && Callee->isDeclaration() &&
        !Callee->hasMetadata(LLVMContext::MD_callback))
      return true;

    if (!Callee->getReturnType()->isVoidTy() && !CB.use_empty()) {
      IRPosition CBRetPos = IRPosition::callsite_returned(CB);
      bool UsedAssumedInformation = false;
      getAssumedSimplified(CBRetPos, nullptr, UsedAssumedInformation,
                           AA::Intraprocedural);

      if (AttributeFuncs::isNoFPClassCompatibleType(Callee->getReturnType()))
        getOrCreateAAFor<AANoFPClass>(CBInstPos);
    }

    const AttributeList &CBAttrs = CBFnPos.getAttrList();
    for (int I = 0, E = CB.arg_size(); I < E; ++I) {

      IRPosition CBArgPos = IRPosition::callsite_argument(CB, I);
      AttributeSet CBArgAttrs = CBAttrs.getParamAttrs(I);

      // Every call site argument might be dead.
      getOrCreateAAFor<AAIsDead>(CBArgPos);

      // Call site argument might be simplified. We have to go through the
      // Attributor interface though as outside AAs can register custom
      // simplification callbacks.
      bool UsedAssumedInformation = false;
      getAssumedSimplified(CBArgPos, /* AA */ nullptr, UsedAssumedInformation,
                           AA::Intraprocedural);

      // Every call site argument might be marked "noundef".
      checkAndQueryIRAttr<Attribute::NoUndef, AANoUndef>(CBArgPos, CBArgAttrs);

      Type *ArgTy = CB.getArgOperand(I)->getType();

      if (!ArgTy->isPointerTy()) {
        if (AttributeFuncs::isNoFPClassCompatibleType(ArgTy))
          getOrCreateAAFor<AANoFPClass>(CBArgPos);

        continue;
      }

      // Call site argument attribute "non-null".
      checkAndQueryIRAttr<Attribute::NonNull, AANonNull>(CBArgPos, CBArgAttrs);

      // Call site argument attribute "captures(none)".
      checkAndQueryIRAttr<Attribute::Captures, AANoCapture>(
          CBArgPos, CBArgAttrs, /*SkipHasAttrCheck=*/true);

      // Call site argument attribute "no-alias".
      checkAndQueryIRAttr<Attribute::NoAlias, AANoAlias>(CBArgPos, CBArgAttrs);

      // Call site argument attribute "dereferenceable".
      getOrCreateAAFor<AADereferenceable>(CBArgPos);

      // Call site argument attribute "align".
      getOrCreateAAFor<AAAlign>(CBArgPos);

      // Call site argument attribute
      // "readnone/readonly/writeonly/..."
      if (!CBAttrs.hasParamAttr(I, Attribute::ReadNone))
        getOrCreateAAFor<AAMemoryBehavior>(CBArgPos);

      // Call site argument attribute "nofree".
      checkAndQueryIRAttr<Attribute::NoFree, AANoFree>(CBArgPos, CBArgAttrs);
    }
    return true;
  };

  auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F);
  [[maybe_unused]] bool Success;
  bool UsedAssumedInformation = false;
  Success = checkForAllInstructionsImpl(
      nullptr, OpcodeInstMap, CallSitePred, nullptr, nullptr,
      {(unsigned)Instruction::Invoke, (unsigned)Instruction::CallBr,
       (unsigned)Instruction::Call},
      UsedAssumedInformation);
  assert(Success && "Expected the check call to be successful!");

  auto LoadStorePred = [&](Instruction &I) -> bool {
    if (auto *LI = dyn_cast<LoadInst>(&I)) {
      getOrCreateAAFor<AAAlign>(IRPosition::value(*LI->getPointerOperand()));
      if (SimplifyAllLoads)
        getAssumedSimplified(IRPosition::value(I), nullptr,
                             UsedAssumedInformation, AA::Intraprocedural);
      getOrCreateAAFor<AAInvariantLoadPointer>(
          IRPosition::value(*LI->getPointerOperand()));
      getOrCreateAAFor<AAAddressSpace>(
          IRPosition::value(*LI->getPointerOperand()));
    } else {
      auto &SI = cast<StoreInst>(I);
      getOrCreateAAFor<AAIsDead>(IRPosition::inst(I));
      getAssumedSimplified(IRPosition::value(*SI.getValueOperand()), nullptr,
                           UsedAssumedInformation, AA::Intraprocedural);
      getOrCreateAAFor<AAAlign>(IRPosition::value(*SI.getPointerOperand()));
      getOrCreateAAFor<AAAddressSpace>(
          IRPosition::value(*SI.getPointerOperand()));
    }
    return true;
  };
  Success = checkForAllInstructionsImpl(
      nullptr, OpcodeInstMap, LoadStorePred, nullptr, nullptr,
      {(unsigned)Instruction::Load, (unsigned)Instruction::Store},
      UsedAssumedInformation);
  assert(Success && "Expected the check call to be successful!");

  // AllocaInstPredicate
  auto AAAllocationInfoPred = [&](Instruction &I) -> bool {
    getOrCreateAAFor<AAAllocationInfo>(IRPosition::value(I));
    return true;
  };

  Success = checkForAllInstructionsImpl(
      nullptr, OpcodeInstMap, AAAllocationInfoPred, nullptr, nullptr,
      {(unsigned)Instruction::Alloca}, UsedAssumedInformation);
  assert(Success && "Expected the check call to be successful!");
}

bool Attributor::isClosedWorldModule() const {
  if (CloseWorldAssumption.getNumOccurrences())
    return CloseWorldAssumption;
  return isModulePass() && Configuration.IsClosedWorldModule;
}

/// Helpers to ease debugging through output streams and print calls.
///
///{
raw_ostream &llvm::operator<<(raw_ostream &OS, ChangeStatus S) {
  return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged");
}

raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) {
  switch (AP) {
  case IRPosition::IRP_INVALID:
    return OS << "inv";
  case IRPosition::IRP_FLOAT:
    return OS << "flt";
  case IRPosition::IRP_RETURNED:
    return OS << "fn_ret";
  case IRPosition::IRP_CALL_SITE_RETURNED:
    return OS << "cs_ret";
  case IRPosition::IRP_FUNCTION:
    return OS << "fn";
  case IRPosition::IRP_CALL_SITE:
    return OS << "cs";
  case IRPosition::IRP_ARGUMENT:
    return OS << "arg";
  case IRPosition::IRP_CALL_SITE_ARGUMENT:
    return OS << "cs_arg";
  }
  llvm_unreachable("Unknown attribute position!");
}

raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) {
  const Value &AV = Pos.getAssociatedValue();
  OS << "{" << Pos.getPositionKind() << ":" << AV.getName() << " ["
     << Pos.getAnchorValue().getName() << "@" << Pos.getCallSiteArgNo() << "]";

  if (Pos.hasCallBaseContext())
    OS << "[cb_context:" << *Pos.getCallBaseContext() << "]";
  return OS << "}";
}

raw_ostream &llvm::operator<<(raw_ostream &OS, const IntegerRangeState &S) {
  OS << "range-state(" << S.getBitWidth() << ")<";
  S.getKnown().print(OS);
  OS << " / ";
  S.getAssumed().print(OS);
  OS << ">";

  return OS << static_cast<const AbstractState &>(S);
}

raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) {
  return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : ""));
}

raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractAttribute &AA) {
  AA.print(OS);
  return OS;
}

raw_ostream &llvm::operator<<(raw_ostream &OS,
                              const PotentialConstantIntValuesState &S) {
  OS << "set-state(< {";
  if (!S.isValidState())
    OS << "full-set";
  else {
    for (const auto &It : S.getAssumedSet())
      OS << It << ", ";
    if (S.undefIsContained())
      OS << "undef ";
  }
  OS << "} >)";

  return OS;
}

raw_ostream &llvm::operator<<(raw_ostream &OS,
                              const PotentialLLVMValuesState &S) {
  OS << "set-state(< {";
  if (!S.isValidState())
    OS << "full-set";
  else {
    for (const auto &It : S.getAssumedSet()) {
      if (auto *F = dyn_cast<Function>(It.first.getValue()))
        OS << "@" << F->getName() << "[" << int(It.second) << "], ";
      else
        OS << *It.first.getValue() << "[" << int(It.second) << "], ";
    }
    if (S.undefIsContained())
      OS << "undef ";
  }
  OS << "} >)";

  return OS;
}

void AbstractAttribute::print(Attributor *A, raw_ostream &OS) const {
  OS << "[";
  OS << getName();
  OS << "] for CtxI ";

  if (auto *I = getCtxI()) {
    OS << "'";
    I->print(OS);
    OS << "'";
  } else
    OS << "<<null inst>>";

  OS << " at position " << getIRPosition() << " with state " << getAsStr(A)
     << '\n';
}

void AbstractAttribute::printWithDeps(raw_ostream &OS) const {
  print(OS);

  for (const auto &DepAA : Deps) {
    auto *AA = DepAA.getPointer();
    OS << "  updates ";
    AA->print(OS);
  }

  OS << '\n';
}

raw_ostream &llvm::operator<<(raw_ostream &OS,
                              const AAPointerInfo::Access &Acc) {
  OS << " [" << Acc.getKind() << "] " << *Acc.getRemoteInst();
  if (Acc.getLocalInst() != Acc.getRemoteInst())
    OS << " via " << *Acc.getLocalInst();
  if (Acc.getContent()) {
    if (*Acc.getContent())
      OS << " [" << **Acc.getContent() << "]";
    else
      OS << " [ <unknown> ]";
  }
  return OS;
}
///}

/// ----------------------------------------------------------------------------
///                       Pass (Manager) Boilerplate
/// ----------------------------------------------------------------------------

static bool runAttributorOnFunctions(InformationCache &InfoCache,
                                     SetVector<Function *> &Functions,
                                     AnalysisGetter &AG,
                                     CallGraphUpdater &CGUpdater,
                                     bool DeleteFns, bool IsModulePass) {
  if (Functions.empty())
    return false;

  LLVM_DEBUG({
    dbgs() << "[Attributor] Run on module with " << Functions.size()
           << " functions:\n";
    for (Function *Fn : Functions)
      dbgs() << "  - " << Fn->getName() << "\n";
  });

  // Create an Attributor and initially empty information cache that is filled
  // while we identify default attribute opportunities.
  AttributorConfig AC(CGUpdater);
  AC.IsModulePass = IsModulePass;
  AC.DeleteFns = DeleteFns;

  /// Tracking callback for specialization of indirect calls.
  DenseMap<CallBase *, std::unique_ptr<SmallPtrSet<Function *, 8>>>
      IndirectCalleeTrackingMap;
  if (MaxSpecializationPerCB.getNumOccurrences()) {
    AC.IndirectCalleeSpecializationCallback =
        [&](Attributor &, const AbstractAttribute &AA, CallBase &CB,
            Function &Callee, unsigned) {
          if (MaxSpecializationPerCB == 0)
            return false;
          auto &Set = IndirectCalleeTrackingMap[&CB];
          if (!Set)
            Set = std::make_unique<SmallPtrSet<Function *, 8>>();
          if (Set->size() >= MaxSpecializationPerCB)
            return Set->contains(&Callee);
          Set->insert(&Callee);
          return true;
        };
  }

  Attributor A(Functions, InfoCache, AC);

  // Create shallow wrappers for all functions that are not IPO amendable
  if (AllowShallowWrappers)
    for (Function *F : Functions)
      if (!A.isFunctionIPOAmendable(*F))
        Attributor::createShallowWrapper(*F);

  // Internalize non-exact functions
  // TODO: for now we eagerly internalize functions without calculating the
  //       cost, we need a cost interface to determine whether internalizing
  //       a function is "beneficial"
  if (AllowDeepWrapper) {
    unsigned FunSize = Functions.size();
    for (unsigned u = 0; u < FunSize; u++) {
      Function *F = Functions[u];
      if (!F->isDeclaration() && !F->isDefinitionExact() && !F->use_empty() &&
          !GlobalValue::isInterposableLinkage(F->getLinkage())) {
        Function *NewF = Attributor::internalizeFunction(*F);
        assert(NewF && "Could not internalize function.");
        Functions.insert(NewF);

        // Update call graph
        CGUpdater.replaceFunctionWith(*F, *NewF);
        for (const Use &U : NewF->uses())
          if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
            auto *CallerF = CB->getCaller();
            CGUpdater.reanalyzeFunction(*CallerF);
          }
      }
    }
  }

  for (Function *F : Functions) {
    if (F->isDeclaration())
      continue;

    if (F->hasExactDefinition())
      NumFnWithExactDefinition++;
    else
      NumFnWithoutExactDefinition++;

    // We look at internal functions only on-demand but if any use is not a
    // direct call or outside the current set of analyzed functions, we have
    // to do it eagerly.
    if (F->hasLocalLinkage()) {
      if (llvm::all_of(F->uses(), [&Functions](const Use &U) {
            const auto *CB = dyn_cast<CallBase>(U.getUser());
            return CB && CB->isCallee(&U) &&
                   Functions.count(const_cast<Function *>(CB->getCaller()));
          }))
        continue;
    }

    // Populate the Attributor with abstract attribute opportunities in the
    // function and the information cache with IR information.
    A.identifyDefaultAbstractAttributes(*F);
  }

  ChangeStatus Changed = A.run();

  LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()
                    << " functions, result: " << Changed << ".\n");
  return Changed == ChangeStatus::CHANGED;
}

static bool runAttributorLightOnFunctions(InformationCache &InfoCache,
                                          SetVector<Function *> &Functions,
                                          AnalysisGetter &AG,
                                          CallGraphUpdater &CGUpdater,
                                          FunctionAnalysisManager &FAM,
                                          bool IsModulePass) {
  if (Functions.empty())
    return false;

  LLVM_DEBUG({
    dbgs() << "[AttributorLight] Run on module with " << Functions.size()
           << " functions:\n";
    for (Function *Fn : Functions)
      dbgs() << "  - " << Fn->getName() << "\n";
  });

  // Create an Attributor and initially empty information cache that is filled
  // while we identify default attribute opportunities.
  AttributorConfig AC(CGUpdater);
  AC.IsModulePass = IsModulePass;
  AC.DeleteFns = false;
  DenseSet<const char *> Allowed(
      {&AAWillReturn::ID, &AANoUnwind::ID, &AANoRecurse::ID, &AANoSync::ID,
       &AANoFree::ID, &AANoReturn::ID, &AAMemoryLocation::ID,
       &AAMemoryBehavior::ID, &AAUnderlyingObjects::ID, &AANoCapture::ID,
       &AAInterFnReachability::ID, &AAIntraFnReachability::ID, &AACallEdges::ID,
       &AANoFPClass::ID, &AAMustProgress::ID, &AANonNull::ID,
       &AADenormalFPMath::ID});
  AC.Allowed = &Allowed;
  AC.UseLiveness = false;

  Attributor A(Functions, InfoCache, AC);

  for (Function *F : Functions) {
    if (F->isDeclaration())
      continue;

    if (F->hasExactDefinition())
      NumFnWithExactDefinition++;
    else
      NumFnWithoutExactDefinition++;

    // We look at internal functions only on-demand but if any use is not a
    // direct call or outside the current set of analyzed functions, we have
    // to do it eagerly.
    if (AC.UseLiveness && F->hasLocalLinkage()) {
      if (llvm::all_of(F->uses(), [&Functions](const Use &U) {
            const auto *CB = dyn_cast<CallBase>(U.getUser());
            return CB && CB->isCallee(&U) &&
                   Functions.count(const_cast<Function *>(CB->getCaller()));
          }))
        continue;
    }

    // Populate the Attributor with abstract attribute opportunities in the
    // function and the information cache with IR information.
    A.identifyDefaultAbstractAttributes(*F);
  }

  ChangeStatus Changed = A.run();

  if (Changed == ChangeStatus::CHANGED) {
    // Invalidate analyses for modified functions so that we don't have to
    // invalidate all analyses for all functions in this SCC.
    PreservedAnalyses FuncPA;
    // We haven't changed the CFG for modified functions.
    FuncPA.preserveSet<CFGAnalyses>();
    for (Function *Changed : A.getModifiedFunctions()) {
      FAM.invalidate(*Changed, FuncPA);
      // Also invalidate any direct callers of changed functions since analyses
      // may care about attributes of direct callees. For example, MemorySSA
      // cares about whether or not a call's callee modifies memory and queries
      // that through function attributes.
      for (auto *U : Changed->users()) {
        if (auto *Call = dyn_cast<CallBase>(U)) {
          if (Call->getCalledFunction() == Changed)
            FAM.invalidate(*Call->getFunction(), FuncPA);
        }
      }
    }
  }
  LLVM_DEBUG(dbgs() << "[Attributor] Done with " << Functions.size()
                    << " functions, result: " << Changed << ".\n");
  return Changed == ChangeStatus::CHANGED;
}

void AADepGraph::viewGraph() { llvm::ViewGraph(this, "Dependency Graph"); }

void AADepGraph::dumpGraph() {
  static std::atomic<int> CallTimes;
  std::string Prefix;

  if (!DepGraphDotFileNamePrefix.empty())
    Prefix = DepGraphDotFileNamePrefix;
  else
    Prefix = "dep_graph";
  std::string Filename =
      Prefix + "_" + std::to_string(CallTimes.load()) + ".dot";

  outs() << "Dependency graph dump to " << Filename << ".\n";

  std::error_code EC;

  raw_fd_ostream File(Filename, EC, sys::fs::OF_TextWithCRLF);
  if (!EC)
    llvm::WriteGraph(File, this);

  CallTimes++;
}

void AADepGraph::print() {
  for (auto DepAA : SyntheticRoot.Deps)
    cast<AbstractAttribute>(DepAA.getPointer())->printWithDeps(outs());
}

PreservedAnalyses AttributorPass::run(Module &M, ModuleAnalysisManager &AM) {
  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
  AnalysisGetter AG(FAM);

  SetVector<Function *> Functions;
  for (Function &F : M)
    Functions.insert(&F);

  CallGraphUpdater CGUpdater;
  BumpPtrAllocator Allocator;
  InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
  if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
                               /* DeleteFns */ true, /* IsModulePass */ true)) {
    // FIXME: Think about passes we will preserve and add them here.
    return PreservedAnalyses::none();
  }
  return PreservedAnalyses::all();
}

PreservedAnalyses AttributorCGSCCPass::run(LazyCallGraph::SCC &C,
                                           CGSCCAnalysisManager &AM,
                                           LazyCallGraph &CG,
                                           CGSCCUpdateResult &UR) {
  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
  AnalysisGetter AG(FAM);

  SetVector<Function *> Functions;
  for (LazyCallGraph::Node &N : C)
    Functions.insert(&N.getFunction());

  if (Functions.empty())
    return PreservedAnalyses::all();

  Module &M = *Functions.back()->getParent();
  CallGraphUpdater CGUpdater;
  CGUpdater.initialize(CG, C, AM, UR);
  BumpPtrAllocator Allocator;
  InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions);
  if (runAttributorOnFunctions(InfoCache, Functions, AG, CGUpdater,
                               /* DeleteFns */ false,
                               /* IsModulePass */ false)) {
    // FIXME: Think about passes we will preserve and add them here.
    PreservedAnalyses PA;
    PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
    return PA;
  }
  return PreservedAnalyses::all();
}

PreservedAnalyses AttributorLightPass::run(Module &M,
                                           ModuleAnalysisManager &AM) {
  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
  AnalysisGetter AG(FAM, /* CachedOnly */ true);

  SetVector<Function *> Functions;
  for (Function &F : M)
    Functions.insert(&F);

  CallGraphUpdater CGUpdater;
  BumpPtrAllocator Allocator;
  InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ nullptr);
  if (runAttributorLightOnFunctions(InfoCache, Functions, AG, CGUpdater, FAM,
                                    /* IsModulePass */ true)) {
    PreservedAnalyses PA;
    // We have not added or removed functions.
    PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
    // We already invalidated all relevant function analyses above.
    PA.preserveSet<AllAnalysesOn<Function>>();
    return PA;
  }
  return PreservedAnalyses::all();
}

PreservedAnalyses AttributorLightCGSCCPass::run(LazyCallGraph::SCC &C,
                                                CGSCCAnalysisManager &AM,
                                                LazyCallGraph &CG,
                                                CGSCCUpdateResult &UR) {
  FunctionAnalysisManager &FAM =
      AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager();
  AnalysisGetter AG(FAM);

  SetVector<Function *> Functions;
  for (LazyCallGraph::Node &N : C)
    Functions.insert(&N.getFunction());

  if (Functions.empty())
    return PreservedAnalyses::all();

  Module &M = *Functions.back()->getParent();
  CallGraphUpdater CGUpdater;
  CGUpdater.initialize(CG, C, AM, UR);
  BumpPtrAllocator Allocator;
  InformationCache InfoCache(M, AG, Allocator, /* CGSCC */ &Functions);
  if (runAttributorLightOnFunctions(InfoCache, Functions, AG, CGUpdater, FAM,
                                    /* IsModulePass */ false)) {
    PreservedAnalyses PA;
    // We have not added or removed functions.
    PA.preserve<FunctionAnalysisManagerCGSCCProxy>();
    // We already invalidated all relevant function analyses above.
    PA.preserveSet<AllAnalysesOn<Function>>();
    return PA;
  }
  return PreservedAnalyses::all();
}
namespace llvm {

template <> struct GraphTraits<AADepGraphNode *> {
  using NodeRef = AADepGraphNode *;
  using DepTy = PointerIntPair<AADepGraphNode *, 1>;
  using EdgeRef = PointerIntPair<AADepGraphNode *, 1>;

  static NodeRef getEntryNode(AADepGraphNode *DGN) { return DGN; }
  static NodeRef DepGetVal(const DepTy &DT) { return DT.getPointer(); }

  using ChildIteratorType =
      mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>;
  using ChildEdgeIteratorType = AADepGraphNode::DepSetTy::iterator;

  static ChildIteratorType child_begin(NodeRef N) { return N->child_begin(); }

  static ChildIteratorType child_end(NodeRef N) { return N->child_end(); }
};

template <>
struct GraphTraits<AADepGraph *> : public GraphTraits<AADepGraphNode *> {
  static NodeRef getEntryNode(AADepGraph *DG) { return DG->GetEntryNode(); }

  using nodes_iterator =
      mapped_iterator<AADepGraphNode::DepSetTy::iterator, decltype(&DepGetVal)>;

  static nodes_iterator nodes_begin(AADepGraph *DG) { return DG->begin(); }

  static nodes_iterator nodes_end(AADepGraph *DG) { return DG->end(); }
};

template <> struct DOTGraphTraits<AADepGraph *> : public DefaultDOTGraphTraits {
  DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}

  static std::string getNodeLabel(const AADepGraphNode *Node,
                                  const AADepGraph *DG) {
    std::string AAString;
    raw_string_ostream O(AAString);
    Node->print(O);
    return AAString;
  }
};

} // end namespace llvm
