llvm/llvm/lib/Transforms/IPO/AttributorAttributes.cpp

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

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

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

usingnamespacellvm;

#define DEBUG_TYPE

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

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

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

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

static cl::opt<unsigned, true> MaxPotentialValues(
    "attributor-max-potential-values", cl::Hidden,
    cl::desc("Maximum number of potential values to be "
             "tracked for each position."),
    cl::location(llvm::PotentialConstantIntValuesState::MaxPotentialValues),
    cl::init(7));

static cl::opt<int> MaxPotentialValuesIterations(
    "attributor-max-potential-values-iterations", cl::Hidden,
    cl::desc(
        "Maximum number of iterations we keep dismantling potential values."),
    cl::init(64));

STATISTIC(NumAAs, "Number of abstract attributes created");
STATISTIC(NumIndirectCallsPromoted, "Number of indirect calls promoted");

// Some helper macros to deal with statistics tracking.
//
// Usage:
// For simple IR attribute tracking overload trackStatistics in the abstract
// attribute and choose the right STATS_DECLTRACK_********* macro,
// e.g.,:
//  void trackStatistics() const override {
//    STATS_DECLTRACK_ARG_ATTR(returned)
//  }
// If there is a single "increment" side one can use the macro
// STATS_DECLTRACK with a custom message. If there are multiple increment
// sides, STATS_DECL and STATS_TRACK can also be used separately.
//
#define BUILD_STAT_MSG_IR_ATTR(TYPE, NAME)
#define BUILD_STAT_NAME(NAME, TYPE)
#define STATS_DECL_(NAME, MSG)
#define STATS_DECL(NAME, TYPE, MSG)
#define STATS_TRACK(NAME, TYPE)
#define STATS_DECLTRACK(NAME, TYPE, MSG)
#define STATS_DECLTRACK_ARG_ATTR(NAME)
#define STATS_DECLTRACK_CSARG_ATTR(NAME)
#define STATS_DECLTRACK_FN_ATTR(NAME)
#define STATS_DECLTRACK_CS_ATTR(NAME)
#define STATS_DECLTRACK_FNRET_ATTR(NAME)
#define STATS_DECLTRACK_CSRET_ATTR(NAME)
#define STATS_DECLTRACK_FLOATING_ATTR(NAME)

// Specialization of the operator<< for abstract attributes subclasses. This
// disambiguates situations where multiple operators are applicable.
llvm // namespace llvm

static bool mayBeInCycle(const CycleInfo *CI, const Instruction *I,
                         bool HeaderOnly, Cycle **CPtr = nullptr) {}

/// Checks if a type could have padding bytes.
static bool isDenselyPacked(Type *Ty, const DataLayout &DL) {}

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

/// Helper function to create a pointer based on \p Ptr, and advanced by \p
/// Offset bytes.
static Value *constructPointer(Value *Ptr, int64_t Offset,
                               IRBuilder<NoFolder> &IRB) {}

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

static const Value *
getMinimalBaseOfPointer(Attributor &A, const AbstractAttribute &QueryingAA,
                        const Value *Ptr, int64_t &BytesOffset,
                        const DataLayout &DL, bool AllowNonInbounds = false) {}

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

namespace {
/// Helper class for generic deduction: return value -> returned position.
template <typename AAType, typename BaseType,
          typename StateType = typename BaseType::StateType,
          bool PropagateCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind,
          bool RecurseForSelectAndPHI = true>
struct AAReturnedFromReturnedValues : public BaseType {};

/// Clamp the information known at all call sites for a given argument
/// (identified by \p QueryingAA) into \p S.
template <typename AAType, typename StateType = typename AAType::StateType,
          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
                                        StateType &S) {}

/// This function is the bridge between argument position and the call base
/// context.
template <typename AAType, typename BaseType,
          typename StateType = typename AAType::StateType,
          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
bool getArgumentStateFromCallBaseContext(Attributor &A,
                                         BaseType &QueryingAttribute,
                                         IRPosition &Pos, StateType &State) {}

/// Helper class for generic deduction: call site argument -> argument position.
template <typename AAType, typename BaseType,
          typename StateType = typename AAType::StateType,
          bool BridgeCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
struct AAArgumentFromCallSiteArguments : public BaseType {};

/// Helper class for generic replication: function returned -> cs returned.
template <typename AAType, typename BaseType,
          typename StateType = typename BaseType::StateType,
          bool IntroduceCallBaseContext = false,
          Attribute::AttrKind IRAttributeKind = AAType::IRAttributeKind>
struct AACalleeToCallSite : public BaseType {};

/// Helper function to accumulate uses.
template <class AAType, typename StateType = typename AAType::StateType>
static void followUsesInContext(AAType &AA, Attributor &A,
                                MustBeExecutedContextExplorer &Explorer,
                                const Instruction *CtxI,
                                SetVector<const Use *> &Uses,
                                StateType &State) {}

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

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

namespace llvm {
namespace AA {
namespace PointerInfo {

struct State;

} // namespace PointerInfo
} // namespace AA

/// Helper for AA::PointerInfo::Access DenseMap/Set usage.
template <>
struct DenseMapInfo<AAPointerInfo::Access> : DenseMapInfo<Instruction *> {};

/// Helper that allows RangeTy as a key in a DenseMap.
template <> struct DenseMapInfo<AA::RangeTy> {};

/// Helper for AA::PointerInfo::Access DenseMap/Set usage ignoring everythign
/// but the instruction
struct AccessAsInstructionInfo : DenseMapInfo<Instruction *> {};

} // namespace llvm

/// A type to track pointer/struct usage and accesses for AAPointerInfo.
struct AA::PointerInfo::State : public AbstractState {};

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

namespace {

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

struct AAPointerInfoImpl
    : public StateWrapper<AA::PointerInfo::State, AAPointerInfo> {};

struct AAPointerInfoFloating : public AAPointerInfoImpl {};

bool AAPointerInfoFloating::collectConstantsForGEP(Attributor &A,
                                                   const DataLayout &DL,
                                                   OffsetInfo &UsrOI,
                                                   const OffsetInfo &PtrOI,
                                                   const GEPOperator *GEP) {}

ChangeStatus AAPointerInfoFloating::updateImpl(Attributor &A) {}

struct AAPointerInfoReturned final : AAPointerInfoImpl {};

struct AAPointerInfoArgument final : AAPointerInfoFloating {};

struct AAPointerInfoCallSiteArgument final : AAPointerInfoFloating {};

struct AAPointerInfoCallSiteReturned final : AAPointerInfoFloating {};
} // namespace

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

namespace {
struct AANoUnwindImpl : AANoUnwind {};

struct AANoUnwindFunction final : public AANoUnwindImpl {};

/// NoUnwind attribute deduction for a call sites.
struct AANoUnwindCallSite final
    : AACalleeToCallSite<AANoUnwind, AANoUnwindImpl> {};
} // namespace

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

bool AANoSync::isAlignedBarrier(const CallBase &CB, bool ExecutedAligned) {}

bool AANoSync::isNonRelaxedAtomic(const Instruction *I) {}

/// Return true if this intrinsic is nosync.  This is only used for intrinsics
/// which would be nosync except that they have a volatile flag.  All other
/// intrinsics are simply annotated with the nosync attribute in Intrinsics.td.
bool AANoSync::isNoSyncIntrinsic(const Instruction *I) {}

namespace {
struct AANoSyncImpl : AANoSync {};

ChangeStatus AANoSyncImpl::updateImpl(Attributor &A) {}

struct AANoSyncFunction final : public AANoSyncImpl {};

/// NoSync attribute deduction for a call sites.
struct AANoSyncCallSite final : AACalleeToCallSite<AANoSync, AANoSyncImpl> {};
} // namespace

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

namespace {
struct AANoFreeImpl : public AANoFree {};

struct AANoFreeFunction final : public AANoFreeImpl {};

/// NoFree attribute deduction for a call sites.
struct AANoFreeCallSite final : AACalleeToCallSite<AANoFree, AANoFreeImpl> {};

/// NoFree attribute for floating values.
struct AANoFreeFloating : AANoFreeImpl {};

/// NoFree attribute for a call site argument.
struct AANoFreeArgument final : AANoFreeFloating {};

/// NoFree attribute for call site arguments.
struct AANoFreeCallSiteArgument final : AANoFreeFloating {};

/// NoFree attribute for function return value.
struct AANoFreeReturned final : AANoFreeFloating {};

/// NoFree attribute deduction for a call site return value.
struct AANoFreeCallSiteReturned final : AANoFreeFloating {};
} // namespace

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

bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {}

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

struct AANonNullImpl : AANonNull {};

/// NonNull attribute for a floating value.
struct AANonNullFloating : public AANonNullImpl {};

/// NonNull attribute for function return value.
struct AANonNullReturned final
    : AAReturnedFromReturnedValues<AANonNull, AANonNull, AANonNull::StateType,
                                   false, AANonNull::IRAttributeKind, false> {};

/// NonNull attribute for function argument.
struct AANonNullArgument final
    : AAArgumentFromCallSiteArguments<AANonNull, AANonNullImpl> {};

struct AANonNullCallSiteArgument final : AANonNullFloating {};

/// NonNull attribute for a call site return position.
struct AANonNullCallSiteReturned final
    : AACalleeToCallSite<AANonNull, AANonNullImpl> {};
} // namespace

/// ------------------------ Must-Progress Attributes --------------------------
namespace {
struct AAMustProgressImpl : public AAMustProgress {};

struct AAMustProgressFunction final : AAMustProgressImpl {};

/// MustProgress attribute deduction for a call sites.
struct AAMustProgressCallSite final : AAMustProgressImpl {};
} // namespace

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

namespace {
struct AANoRecurseImpl : public AANoRecurse {};

struct AANoRecurseFunction final : AANoRecurseImpl {};

/// NoRecurse attribute deduction for a call sites.
struct AANoRecurseCallSite final
    : AACalleeToCallSite<AANoRecurse, AANoRecurseImpl> {};
} // namespace

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

namespace {
struct AANonConvergentImpl : public AANonConvergent {};

struct AANonConvergentFunction final : AANonConvergentImpl {};
} // namespace

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

namespace {
struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior {};

struct AAUndefinedBehaviorFunction final : AAUndefinedBehaviorImpl {};
} // namespace

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

namespace {
// Helper function that checks whether a function has any cycle which we don't
// know if it is bounded or not.
// Loops with maximum trip count are considered bounded, any other cycle not.
static bool mayContainUnboundedCycle(Function &F, Attributor &A) {}

struct AAWillReturnImpl : public AAWillReturn {};

struct AAWillReturnFunction final : AAWillReturnImpl {};

/// WillReturn attribute deduction for a call sites.
struct AAWillReturnCallSite final
    : AACalleeToCallSite<AAWillReturn, AAWillReturnImpl> {};
} // namespace

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

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

llvm // namespace llvm

namespace {

template <typename BaseTy, typename ToTy>
struct CachedReachabilityAA : public BaseTy {};

struct AAIntraFnReachabilityFunction final
    : public CachedReachabilityAA<AAIntraFnReachability, Instruction> {};
} // namespace

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

bool AANoAlias::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {}

namespace {
struct AANoAliasImpl : AANoAlias {};

/// NoAlias attribute for a floating value.
struct AANoAliasFloating final : AANoAliasImpl {};

/// NoAlias attribute for an argument.
struct AANoAliasArgument final
    : AAArgumentFromCallSiteArguments<AANoAlias, AANoAliasImpl> {};

struct AANoAliasCallSiteArgument final : AANoAliasImpl {};

/// NoAlias attribute for function return value.
struct AANoAliasReturned final : AANoAliasImpl {};

/// NoAlias attribute deduction for a call site return value.
struct AANoAliasCallSiteReturned final
    : AACalleeToCallSite<AANoAlias, AANoAliasImpl> {};
} // namespace

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

namespace {
struct AAIsDeadValueImpl : public AAIsDead {};

struct AAIsDeadFloating : public AAIsDeadValueImpl {};

struct AAIsDeadArgument : public AAIsDeadFloating {};

struct AAIsDeadCallSiteArgument : public AAIsDeadValueImpl {};

struct AAIsDeadCallSiteReturned : public AAIsDeadFloating {};

struct AAIsDeadReturned : public AAIsDeadValueImpl {};

struct AAIsDeadFunction : public AAIsDead {};

static bool
identifyAliveSuccessors(Attributor &A, const CallBase &CB,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {}

static bool
identifyAliveSuccessors(Attributor &A, const InvokeInst &II,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {}

static bool
identifyAliveSuccessors(Attributor &A, const BranchInst &BI,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {}

static bool
identifyAliveSuccessors(Attributor &A, const SwitchInst &SI,
                        AbstractAttribute &AA,
                        SmallVectorImpl<const Instruction *> &AliveSuccessors) {}

ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A) {}

/// Liveness information for a call sites.
struct AAIsDeadCallSite final : AAIsDeadFunction {};
} // namespace

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

namespace {
struct AADereferenceableImpl : AADereferenceable {};

/// Dereferenceable attribute for a floating value.
struct AADereferenceableFloating : AADereferenceableImpl {};

/// Dereferenceable attribute for a return value.
struct AADereferenceableReturned final
    : AAReturnedFromReturnedValues<AADereferenceable, AADereferenceableImpl> {};

/// Dereferenceable attribute for an argument
struct AADereferenceableArgument final
    : AAArgumentFromCallSiteArguments<AADereferenceable,
                                      AADereferenceableImpl> {};

/// Dereferenceable attribute for a call site argument.
struct AADereferenceableCallSiteArgument final : AADereferenceableFloating {};

/// Dereferenceable attribute deduction for a call site return value.
struct AADereferenceableCallSiteReturned final
    : AACalleeToCallSite<AADereferenceable, AADereferenceableImpl> {};
} // namespace

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

namespace {
static unsigned getKnownAlignForUse(Attributor &A, AAAlign &QueryingAA,
                                    Value &AssociatedValue, const Use *U,
                                    const Instruction *I, bool &TrackUse) {}

struct AAAlignImpl : AAAlign {};

/// Align attribute for a floating value.
struct AAAlignFloating : AAAlignImpl {};

/// Align attribute for function return value.
struct AAAlignReturned final
    : AAReturnedFromReturnedValues<AAAlign, AAAlignImpl> {};

/// Align attribute for function argument.
struct AAAlignArgument final
    : AAArgumentFromCallSiteArguments<AAAlign, AAAlignImpl> {};

struct AAAlignCallSiteArgument final : AAAlignFloating {};

/// Align attribute deduction for a call site return value.
struct AAAlignCallSiteReturned final
    : AACalleeToCallSite<AAAlign, AAAlignImpl> {};
} // namespace

/// ------------------ Function No-Return Attribute ----------------------------
namespace {
struct AANoReturnImpl : public AANoReturn {};

struct AANoReturnFunction final : AANoReturnImpl {};

/// NoReturn attribute deduction for a call sites.
struct AANoReturnCallSite final
    : AACalleeToCallSite<AANoReturn, AANoReturnImpl> {};
} // namespace

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

namespace {
/// A class to hold the state of for no-capture attributes.
struct AAInstanceInfoImpl : public AAInstanceInfo {};

/// InstanceInfo attribute for floating values.
struct AAInstanceInfoFloating : AAInstanceInfoImpl {};

/// NoCapture attribute for function arguments.
struct AAInstanceInfoArgument final : AAInstanceInfoFloating {};

/// InstanceInfo attribute for call site arguments.
struct AAInstanceInfoCallSiteArgument final : AAInstanceInfoImpl {};

/// InstanceInfo attribute for function return value.
struct AAInstanceInfoReturned final : AAInstanceInfoImpl {};

/// InstanceInfo attribute deduction for a call site return value.
struct AAInstanceInfoCallSiteReturned final : AAInstanceInfoFloating {};
} // namespace

/// ----------------------- Variable Capturing ---------------------------------
bool AANoCapture::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                                Attribute::AttrKind ImpliedAttributeKind,
                                bool IgnoreSubsumingPositions) {}

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

namespace {
/// A class to hold the state of for no-capture attributes.
struct AANoCaptureImpl : public AANoCapture {};

ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {}

/// NoCapture attribute for function arguments.
struct AANoCaptureArgument final : AANoCaptureImpl {};

/// NoCapture attribute for call site arguments.
struct AANoCaptureCallSiteArgument final : AANoCaptureImpl {};

/// NoCapture attribute for floating values.
struct AANoCaptureFloating final : AANoCaptureImpl {};

/// NoCapture attribute for function return value.
struct AANoCaptureReturned final : AANoCaptureImpl {};

/// NoCapture attribute deduction for a call site return value.
struct AANoCaptureCallSiteReturned final : AANoCaptureImpl {};
} // namespace

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

bool ValueSimplifyStateType::unionAssumed(std::optional<Value *> Other) {}

namespace {
struct AAValueSimplifyImpl : AAValueSimplify {};

struct AAValueSimplifyArgument final : AAValueSimplifyImpl {};

struct AAValueSimplifyReturned : AAValueSimplifyImpl {};

struct AAValueSimplifyFloating : AAValueSimplifyImpl {};

struct AAValueSimplifyFunction : AAValueSimplifyImpl {};

struct AAValueSimplifyCallSite : AAValueSimplifyFunction {};

struct AAValueSimplifyCallSiteReturned : AAValueSimplifyImpl {};

struct AAValueSimplifyCallSiteArgument : AAValueSimplifyFloating {};
} // namespace

/// ----------------------- Heap-To-Stack Conversion ---------------------------
namespace {
struct AAHeapToStackFunction final : public AAHeapToStack {};

ChangeStatus AAHeapToStackFunction::updateImpl(Attributor &A) {}
} // namespace

/// ----------------------- Privatizable Pointers ------------------------------
namespace {
struct AAPrivatizablePtrImpl : public AAPrivatizablePtr {};

// TODO: Do this for call site arguments (probably also other values) as well.

struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {};

struct AAPrivatizablePtrFloating : public AAPrivatizablePtrImpl {};

struct AAPrivatizablePtrCallSiteArgument final
    : public AAPrivatizablePtrFloating {};

struct AAPrivatizablePtrCallSiteReturned final
    : public AAPrivatizablePtrFloating {};

struct AAPrivatizablePtrReturned final : public AAPrivatizablePtrFloating {};
} // namespace

/// -------------------- Memory Behavior Attributes ----------------------------
/// Includes read-none, read-only, and write-only.
/// ----------------------------------------------------------------------------
namespace {
struct AAMemoryBehaviorImpl : public AAMemoryBehavior {};

const Attribute::AttrKind AAMemoryBehaviorImpl::AttrKinds[] =;

/// Memory behavior attribute for a floating value.
struct AAMemoryBehaviorFloating : AAMemoryBehaviorImpl {};

/// Memory behavior attribute for function argument.
struct AAMemoryBehaviorArgument : AAMemoryBehaviorFloating {};

struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {};

/// Memory behavior attribute for a call site return position.
struct AAMemoryBehaviorCallSiteReturned final : AAMemoryBehaviorFloating {};

/// An AA to represent the memory behavior function attributes.
struct AAMemoryBehaviorFunction final : public AAMemoryBehaviorImpl {};

/// AAMemoryBehavior attribute for call sites.
struct AAMemoryBehaviorCallSite final
    : AACalleeToCallSite<AAMemoryBehavior, AAMemoryBehaviorImpl> {};

ChangeStatus AAMemoryBehaviorFunction::updateImpl(Attributor &A) {}

ChangeStatus AAMemoryBehaviorFloating::updateImpl(Attributor &A) {}

bool AAMemoryBehaviorFloating::followUsersOfUseIn(Attributor &A, const Use &U,
                                                  const Instruction *UserI) {}

void AAMemoryBehaviorFloating::analyzeUseIn(Attributor &A, const Use &U,
                                            const Instruction *UserI) {}
} // namespace

/// -------------------- Memory Locations Attributes ---------------------------
/// Includes read-none, argmemonly, inaccessiblememonly,
/// inaccessiblememorargmemonly
/// ----------------------------------------------------------------------------

std::string AAMemoryLocation::getMemoryLocationsAsStr(
    AAMemoryLocation::MemoryLocationsKind MLK) {}

namespace {
struct AAMemoryLocationImpl : public AAMemoryLocation {};

void AAMemoryLocationImpl::categorizePtrValue(
    Attributor &A, const Instruction &I, const Value &Ptr,
    AAMemoryLocation::StateType &State, bool &Changed, unsigned AccessAS) {}

void AAMemoryLocationImpl::categorizeArgumentPointerLocations(
    Attributor &A, CallBase &CB, AAMemoryLocation::StateType &AccessedLocs,
    bool &Changed) {}

AAMemoryLocation::MemoryLocationsKind
AAMemoryLocationImpl::categorizeAccessedLocations(Attributor &A, Instruction &I,
                                                  bool &Changed) {}

/// An AA to represent the memory behavior function attributes.
struct AAMemoryLocationFunction final : public AAMemoryLocationImpl {};

/// AAMemoryLocation attribute for call sites.
struct AAMemoryLocationCallSite final : AAMemoryLocationImpl {};
} // namespace

/// ------------------ denormal-fp-math Attribute -------------------------

namespace {
struct AADenormalFPMathImpl : public AADenormalFPMath {};

struct AADenormalFPMathFunction final : AADenormalFPMathImpl {};
} // namespace

/// ------------------ Value Constant Range Attribute -------------------------

namespace {
struct AAValueConstantRangeImpl : AAValueConstantRange {};

struct AAValueConstantRangeArgument final
    : AAArgumentFromCallSiteArguments<
          AAValueConstantRange, AAValueConstantRangeImpl, IntegerRangeState,
          true /* BridgeCallBaseContext */> {};

struct AAValueConstantRangeReturned
    : AAReturnedFromReturnedValues<AAValueConstantRange,
                                   AAValueConstantRangeImpl,
                                   AAValueConstantRangeImpl::StateType,
                                   /* PropogateCallBaseContext */ true> {};

struct AAValueConstantRangeFloating : AAValueConstantRangeImpl {};

struct AAValueConstantRangeFunction : AAValueConstantRangeImpl {};

struct AAValueConstantRangeCallSite : AAValueConstantRangeFunction {};

struct AAValueConstantRangeCallSiteReturned
    : AACalleeToCallSite<AAValueConstantRange, AAValueConstantRangeImpl,
                         AAValueConstantRangeImpl::StateType,
                         /* IntroduceCallBaseContext */ true> {};
struct AAValueConstantRangeCallSiteArgument : AAValueConstantRangeFloating {};
} // namespace

/// ------------------ Potential Values Attribute -------------------------

namespace {
struct AAPotentialConstantValuesImpl : AAPotentialConstantValues {};

struct AAPotentialConstantValuesArgument final
    : AAArgumentFromCallSiteArguments<AAPotentialConstantValues,
                                      AAPotentialConstantValuesImpl,
                                      PotentialConstantIntValuesState> {};

struct AAPotentialConstantValuesReturned
    : AAReturnedFromReturnedValues<AAPotentialConstantValues,
                                   AAPotentialConstantValuesImpl> {};

struct AAPotentialConstantValuesFloating : AAPotentialConstantValuesImpl {};

struct AAPotentialConstantValuesFunction : AAPotentialConstantValuesImpl {};

struct AAPotentialConstantValuesCallSite : AAPotentialConstantValuesFunction {};

struct AAPotentialConstantValuesCallSiteReturned
    : AACalleeToCallSite<AAPotentialConstantValues,
                         AAPotentialConstantValuesImpl> {};

struct AAPotentialConstantValuesCallSiteArgument
    : AAPotentialConstantValuesFloating {};
} // namespace

/// ------------------------ NoUndef Attribute ---------------------------------
bool AANoUndef::isImpliedByIR(Attributor &A, const IRPosition &IRP,
                              Attribute::AttrKind ImpliedAttributeKind,
                              bool IgnoreSubsumingPositions) {}

namespace {
struct AANoUndefImpl : AANoUndef {};

struct AANoUndefFloating : public AANoUndefImpl {};

struct AANoUndefReturned final
    : AAReturnedFromReturnedValues<AANoUndef, AANoUndefImpl> {};

struct AANoUndefArgument final
    : AAArgumentFromCallSiteArguments<AANoUndef, AANoUndefImpl> {};

struct AANoUndefCallSiteArgument final : AANoUndefFloating {};

struct AANoUndefCallSiteReturned final
    : AACalleeToCallSite<AANoUndef, AANoUndefImpl> {};

/// ------------------------ NoFPClass Attribute -------------------------------

struct AANoFPClassImpl : AANoFPClass {};

struct AANoFPClassFloating : public AANoFPClassImpl {};

struct AANoFPClassReturned final
    : AAReturnedFromReturnedValues<AANoFPClass, AANoFPClassImpl,
                                   AANoFPClassImpl::StateType, false,
                                   Attribute::None, false> {};

struct AANoFPClassArgument final
    : AAArgumentFromCallSiteArguments<AANoFPClass, AANoFPClassImpl> {};

struct AANoFPClassCallSiteArgument final : AANoFPClassFloating {};

struct AANoFPClassCallSiteReturned final
    : AACalleeToCallSite<AANoFPClass, AANoFPClassImpl> {};

struct AACallEdgesImpl : public AACallEdges {};

struct AACallEdgesCallSite : public AACallEdgesImpl {};

struct AACallEdgesFunction : public AACallEdgesImpl {};

/// -------------------AAInterFnReachability Attribute--------------------------

struct AAInterFnReachabilityFunction
    : public CachedReachabilityAA<AAInterFnReachability, Function> {};
} // namespace

template <typename AAType>
static std::optional<Constant *>
askForAssumedConstant(Attributor &A, const AbstractAttribute &QueryingAA,
                      const IRPosition &IRP, Type &Ty) {}

Value *AAPotentialValues::getSingleValue(
    Attributor &A, const AbstractAttribute &AA, const IRPosition &IRP,
    SmallVectorImpl<AA::ValueAndContext> &Values) {}

namespace {
struct AAPotentialValuesImpl : AAPotentialValues {};

struct AAPotentialValuesFloating : AAPotentialValuesImpl {};

struct AAPotentialValuesArgument final : AAPotentialValuesImpl {};

struct AAPotentialValuesReturned : public AAPotentialValuesFloating {};

struct AAPotentialValuesFunction : AAPotentialValuesImpl {};

struct AAPotentialValuesCallSite : AAPotentialValuesFunction {};

struct AAPotentialValuesCallSiteReturned : AAPotentialValuesImpl {};

struct AAPotentialValuesCallSiteArgument : AAPotentialValuesFloating {};
} // namespace

/// ---------------------- Assumption Propagation ------------------------------
namespace {
struct AAAssumptionInfoImpl : public AAAssumptionInfo {};

/// Propagates assumption information from parent functions to all of their
/// successors. An assumption can be propagated if the containing function
/// dominates the called function.
///
/// We start with a "known" set of assumptions already valid for the associated
/// function and an "assumed" set that initially contains all possible
/// assumptions. The assumed set is inter-procedurally updated by narrowing its
/// contents as concrete values are known. The concrete values are seeded by the
/// first nodes that are either entries into the call graph, or contains no
/// assumptions. Each node is updated as the intersection of the assumed state
/// with all of its predecessors.
struct AAAssumptionInfoFunction final : AAAssumptionInfoImpl {};

/// Assumption Info defined for call sites.
struct AAAssumptionInfoCallSite final : AAAssumptionInfoImpl {};
} // namespace

AACallGraphNode *AACallEdgeIterator::operator*() const {}

void AttributorCallGraph::print() {}

/// ------------------------ UnderlyingObjects ---------------------------------

namespace {
struct AAUnderlyingObjectsImpl
    : StateWrapper<BooleanState, AAUnderlyingObjects> {};

struct AAUnderlyingObjectsFloating final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsArgument final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsCallSite final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsCallSiteArgument final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsReturned final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsCallSiteReturned final : AAUnderlyingObjectsImpl {};

struct AAUnderlyingObjectsFunction final : AAUnderlyingObjectsImpl {};
} // namespace

/// ------------------------ Global Value Info  -------------------------------
namespace {
struct AAGlobalValueInfoFloating : public AAGlobalValueInfo {};
} // namespace

/// ------------------------ Indirect Call Info  -------------------------------
namespace {
struct AAIndirectCallInfoCallSite : public AAIndirectCallInfo {};
} // namespace

/// ------------------------ Address Space  ------------------------------------
namespace {

template <typename InstType>
static bool makeChange(Attributor &A, InstType *MemInst, const Use &U,
                       Value *OriginalValue, PointerType *NewPtrTy,
                       bool UseOriginalValue) {}

struct AAAddressSpaceImpl : public AAAddressSpace {};

struct AAAddressSpaceFloating final : AAAddressSpaceImpl {};

struct AAAddressSpaceReturned final : AAAddressSpaceImpl {};

struct AAAddressSpaceCallSiteReturned final : AAAddressSpaceImpl {};

struct AAAddressSpaceArgument final : AAAddressSpaceImpl {};

struct AAAddressSpaceCallSiteArgument final : AAAddressSpaceImpl {};
} // namespace

/// ----------- Allocation Info ----------
namespace {
struct AAAllocationInfoImpl : public AAAllocationInfo {};

struct AAAllocationInfoFloating : AAAllocationInfoImpl {};

struct AAAllocationInfoReturned : AAAllocationInfoImpl {};

struct AAAllocationInfoCallSiteReturned : AAAllocationInfoImpl {};

struct AAAllocationInfoArgument : AAAllocationInfoImpl {};

struct AAAllocationInfoCallSiteArgument : AAAllocationInfoImpl {};
} // namespace

const char AANoUnwind::ID =;
const char AANoSync::ID =;
const char AANoFree::ID =;
const char AANonNull::ID =;
const char AAMustProgress::ID =;
const char AANoRecurse::ID =;
const char AANonConvergent::ID =;
const char AAWillReturn::ID =;
const char AAUndefinedBehavior::ID =;
const char AANoAlias::ID =;
const char AAIntraFnReachability::ID =;
const char AANoReturn::ID =;
const char AAIsDead::ID =;
const char AADereferenceable::ID =;
const char AAAlign::ID =;
const char AAInstanceInfo::ID =;
const char AANoCapture::ID =;
const char AAValueSimplify::ID =;
const char AAHeapToStack::ID =;
const char AAPrivatizablePtr::ID =;
const char AAMemoryBehavior::ID =;
const char AAMemoryLocation::ID =;
const char AAValueConstantRange::ID =;
const char AAPotentialConstantValues::ID =;
const char AAPotentialValues::ID =;
const char AANoUndef::ID =;
const char AANoFPClass::ID =;
const char AACallEdges::ID =;
const char AAInterFnReachability::ID =;
const char AAPointerInfo::ID =;
const char AAAssumptionInfo::ID =;
const char AAUnderlyingObjects::ID =;
const char AAAddressSpace::ID =;
const char AAAllocationInfo::ID =;
const char AAIndirectCallInfo::ID =;
const char AAGlobalValueInfo::ID =;
const char AADenormalFPMath::ID =;

// Macro magic to create the static generator function for attributes that
// follow the naming scheme.

#define SWITCH_PK_INV

#define SWITCH_PK_CREATE

#define CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION

#define CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION

#define CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION

#define CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION

#define CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION

#define CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION

CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION

CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION

CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION

CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION

CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION

CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION

#undef CREATE_FUNCTION_ONLY_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_FUNCTION_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_NON_RET_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_ALL_ABSTRACT_ATTRIBUTE_FOR_POSITION
#undef CREATE_ABSTRACT_ATTRIBUTE_FOR_ONE_POSITION
#undef SWITCH_PK_CREATE
#undef SWITCH_PK_INV