diff --git a/llvm/include/llvm/Bitcode/LLVMBitCodes.h b/llvm/include/llvm/Bitcode/LLVMBitCodes.h --- a/llvm/include/llvm/Bitcode/LLVMBitCodes.h +++ b/llvm/include/llvm/Bitcode/LLVMBitCodes.h @@ -633,6 +633,7 @@ ATTR_KIND_NOFREE = 62, ATTR_KIND_NOSYNC = 63, ATTR_KIND_SANITIZE_MEMTAG = 64, + ATTR_KIND_REACHABILITY = 65, }; enum ComdatSelectionKindCodes { diff --git a/llvm/include/llvm/IR/Attributes.td b/llvm/include/llvm/IR/Attributes.td --- a/llvm/include/llvm/IR/Attributes.td +++ b/llvm/include/llvm/IR/Attributes.td @@ -127,6 +127,9 @@ /// Function must not be optimized. def OptimizeNone : EnumAttr<"optnone">; +/// Reachability from point A to B. +def Reachability: EnumAttr<"reachable">; + /// Function does not access memory. def ReadNone : EnumAttr<"readnone">; diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -1682,6 +1682,38 @@ static const char ID; }; +/// An abstract interface to determine reachability of point A to B. +struct AAReachability + : public IRAttribute { + AAReachability(const IRPosition &IRP) : IRAttribute(IRP) {} + + /// Provide static access to the type of the state. + using StateType = DecIntegerState; + + /// Returns true if instruction is assumed reachable. + bool getAssumedReachability() const { return State.getAssumed(); } + + /// Returns true if instruction is known reachable. + bool isKnownReachability() const { return State.getKnown(); } + + /// See AbstractAttribute::getState(...). + StateType &getState() override { return State; } + + /// See AbstractAttribute::getState(...). + const AbstractState &getState() const override { return State; } + + /// Create an abstract attribute view for the position \p IRP. + static AAReachability &createForPosition(const IRPosition &IRP, + Attributor &A); + + /// Unique ID (due to the unique address) + static const char ID; + +private: + /// The current state of this attribute. + StateType State; +}; + /// An abstract interface for all noalias attributes. struct AANoAlias : public IRAttributehasExactDefinition()) + getState().indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_ARG_ATTR(Reachability) + } +}; + +struct AAReachabilityReturned : public AAReachabilityImpl { + AAReachabilityReturned(const IRPosition &IRP) : AAReachabilityImpl(IRP) {} + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + return getState().indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + return ChangeStatus::UNCHANGED; + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_FNRET_ATTR(Reachability) + } +}; + +struct AAReachabilityCallSiteReturned : public AAReachabilityFloating { + AAReachabilityCallSiteReturned(const IRPosition &IRP) + : AAReachabilityFloating(IRP) {} + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override {} + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_CSRET_ATTR(Reachability) + } +}; + +struct AAReachabilityCallSiteArgument : public AAReachabilityImpl { + AAReachabilityCallSiteArgument(const IRPosition &IRP) + : AAReachabilityImpl(IRP) {} + + /// See AbstractAttribute::initialize(...). + void initialize(Attributor &A) override { + getState().indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::updateImpl(...). + ChangeStatus updateImpl(Attributor &A) override { + return getState().indicatePessimisticFixpoint(); + } + + /// See AbstractAttribute::manifest(...). + ChangeStatus manifest(Attributor &A) override { + return ChangeStatus::UNCHANGED; + } + + /// See AbstractAttribute::trackStatistics() + void trackStatistics() const override { + STATS_DECLTRACK_CSARG_ATTR(Reachability) + } +}; + /// ------------------------ NoAlias Argument Attribute ------------------------ struct AANoAliasImpl : AANoAlias { @@ -5447,6 +5566,9 @@ // Every argument with pointer type might be marked noalias. getOrCreateAAFor(ArgPos); + // Every argument with pointer type might be marked reachable. + getOrCreateAAFor(ArgPos); + // Every argument with pointer type might be marked dereferenceable. getOrCreateAAFor(ArgPos); @@ -5499,6 +5621,9 @@ // Call site argument attribute "no-alias". getOrCreateAAFor(CSArgPos); + // Call site argument attribute "reachable". + getOrCreateAAFor(CSArgPos); + // Call site argument attribute "dereferenceable". getOrCreateAAFor(CSArgPos); @@ -5684,6 +5809,7 @@ const char AANoRecurse::ID = 0; const char AAWillReturn::ID = 0; const char AANoAlias::ID = 0; +const char AAReachability::ID = 0; const char AANoReturn::ID = 0; const char AAIsDead::ID = 0; const char AADereferenceable::ID = 0; @@ -5794,6 +5920,7 @@ CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANonNull) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoAlias) +CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAReachability) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AADereferenceable) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AAAlign) CREATE_VALUE_ABSTRACT_ATTRIBUTE_FOR_POSITION(AANoCapture) diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -869,6 +869,7 @@ case Attribute::NoSync: case Attribute::None: case Attribute::NonNull: + case Attribute::Reachability: case Attribute::ReadNone: case Attribute::ReadOnly: case Attribute::Returned: