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 @@ -674,6 +674,19 @@ int AttributeIdx; }; +/// Helper to tie a abstract state implementation to an abstract attribute. +template +struct StateWrapper : public StateTy, public Base { + /// Provide static access to the type of the state. + using StateType = StateTy; + + /// See AbstractAttribute::getState(...). + StateType &getState() override { return *this; } + + /// See AbstractAttribute::getState(...). + const AbstractState &getState() const override { return *this; } +}; + /// Helper class that provides common functionality to manifest IR attributes. template struct IRAttribute : public IRPosition, public Base { @@ -748,6 +761,7 @@ /// NOTE: The mechanics of adding a new "concrete" abstract attribute are /// described in the file comment. struct AbstractAttribute { + using StateType = AbstractState; /// Virtual destructor. virtual ~AbstractAttribute() {} @@ -763,7 +777,8 @@ virtual void initialize(Attributor &A, InformationCache &InfoCache) {} /// Return the internal abstract state for inspection. - virtual const AbstractState &getState() const = 0; + virtual StateType &getState() = 0; + virtual const StateType &getState() const = 0; /// Return an IR position, see struct IRPosition. virtual const IRPosition &getIRPosition() const = 0; @@ -799,9 +814,6 @@ /// Return an IR position, see struct IRPosition. virtual IRPosition &getIRPosition() = 0; - /// Return the internal abstract state for careful modification. - virtual AbstractState &getState() = 0; - /// The actual update/transfer function which has to be implemented by the /// derived classes. /// @@ -854,41 +866,47 @@ static const char ID; }; -struct AANoUnwind : public IRAttribute { +struct AANoUnwind + : public IRAttribute> { IRPositionConstructorForward(AANoUnwind, IRAttribute); /// Returns true if nounwind is assumed. - virtual bool isAssumedNoUnwind() const = 0; + bool isAssumedNoUnwind() const { return getAssumed(); } /// Returns true if nounwind is known. - virtual bool isKnownNoUnwind() const = 0; + bool isKnownNoUnwind() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; -struct AANoSync : public IRAttribute { +struct AANoSync + : public IRAttribute> { IRPositionConstructorForward(AANoSync, IRAttribute); /// Returns true if "nosync" is assumed. - virtual bool isAssumedNoSync() const = 0; + bool isAssumedNoSync() const { return getAssumed(); } /// Returns true if "nosync" is known. - virtual bool isKnownNoSync() const = 0; + bool isKnownNoSync() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for all nonnull attributes. -struct AANonNull : public IRAttribute { +struct AANonNull + : public IRAttribute> { IRPositionConstructorForward(AANonNull, IRAttribute); /// Return true if we assume that the underlying value is nonnull. - virtual bool isAssumedNonNull() const = 0; + bool isAssumedNonNull() const { return getAssumed(); } /// Return true if we know that underlying value is nonnull. - virtual bool isKnownNonNull() const = 0; + bool isKnownNonNull() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; @@ -896,14 +914,15 @@ /// An abstract attribute for norecurse. struct AANoRecurse - : public IRAttribute { + : public IRAttribute> { IRPositionConstructorForward(AANoRecurse, IRAttribute); - /// Return true if "norecurse" is known. - virtual bool isKnownNoRecurse() const = 0; - /// Return true if "norecurse" is assumed. - virtual bool isAssumedNoRecurse() const = 0; + bool isAssumedNoRecurse() const { return getAssumed(); } + + /// Return true if "norecurse" is known. + bool isKnownNoRecurse() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; @@ -911,63 +930,71 @@ /// An abstract attribute for willreturn. struct AAWillReturn - : public IRAttribute { + : public IRAttribute> { IRPositionConstructorForward(AAWillReturn, IRAttribute); - /// Return true if "willreturn" is known. - virtual bool isKnownWillReturn() const = 0; - /// Return true if "willreturn" is assumed. - virtual bool isAssumedWillReturn() const = 0; + virtual bool isAssumedWillReturn() const { return getAssumed(); } + + /// Return true if "willreturn" is known. + virtual bool isKnownWillReturn() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for all noalias attributes. -struct AANoAlias : public IRAttribute { +struct AANoAlias + : public IRAttribute> { IRPositionConstructorForward(AANoAlias, IRAttribute); /// Return true if we assume that the underlying value is alias. - virtual bool isAssumedNoAlias() const = 0; + bool isAssumedNoAlias() const { return getAssumed(); } /// Return true if we know that underlying value is noalias. - virtual bool isKnownNoAlias() const = 0; + bool isKnownNoAlias() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; /// An AbstractAttribute for nofree. -struct AANoFree : public IRAttribute { +struct AANoFree + : public IRAttribute> { IRPositionConstructorForward(AANoFree, IRAttribute); - /// Return true if "nofree" is known. - virtual bool isKnownNoFree() const = 0; - /// Return true if "nofree" is assumed. - virtual bool isAssumedNoFree() const = 0; + bool isAssumedNoFree() const { return getAssumed(); } + + /// Return true if "nofree" is known. + bool isKnownNoFree() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; /// An AbstractAttribute for noreturn. -struct AANoReturn : public IRAttribute { +struct AANoReturn + : public IRAttribute> { IRPositionConstructorForward(AANoReturn, IRAttribute); - /// Return true if the underlying object is known to never return. - virtual bool isKnownNoReturn() const = 0; - /// Return true if the underlying object is assumed to never return. - virtual bool isAssumedNoReturn() const = 0; + bool isAssumedNoReturn() const { return getAssumed(); } + + /// Return true if the underlying object is known to never return. + bool isKnownNoReturn() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for liveness abstract attribute. -struct AAIsDead : public AbstractAttribute, public IRPosition { +struct AAIsDead : public StateWrapper, + public IRPosition { IRPositionConstructorForward(AAIsDead, IRPosition); /// Returns true if \p BB is assumed dead. @@ -1037,14 +1064,16 @@ }; /// An abstract interface for all align attributes. -struct AAAlign : public IRAttribute { +struct AAAlign + : public IRAttribute> { IRPositionConstructorForward(AAAlign, IRAttribute); /// Return assumed alignment. - virtual unsigned getAssumedAlign() const = 0; + unsigned getAssumedAlign() const { return getAssumed(); } /// Return known alignemnt. - virtual unsigned getKnownAlign() const = 0; + unsigned getKnownAlign() const { return getKnown(); } /// Unique ID (due to the unique address) static const char ID; diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -390,27 +390,15 @@ /// -----------------------NoUnwind Function Attribute-------------------------- -struct AANoUnwindImpl : AANoUnwind, BooleanState { +struct AANoUnwindImpl : AANoUnwind { IRPositionConstructorForward(AANoUnwindImpl, AANoUnwind); - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - const std::string getAsStr() const override { return getAssumed() ? "nounwind" : "may-unwind"; } /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - - /// See AANoUnwind::isAssumedNoUnwind(). - bool isAssumedNoUnwind() const override { return getAssumed(); } - - /// See AANoUnwind::isKnownNoUnwind(). - bool isKnownNoUnwind() const override { return getKnown(); } }; struct AANoUnwindFunction final : public AANoUnwindImpl { @@ -792,15 +780,9 @@ /// ------------------------ NoSync Function Attribute ------------------------- -struct AANoSyncImpl : AANoSync, BooleanState { +struct AANoSyncImpl : AANoSync { IRPositionConstructorForward(AANoSyncImpl, AANoSync); - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - const std::string getAsStr() const override { return getAssumed() ? "nosync" : "may-sync"; } @@ -808,12 +790,6 @@ /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - /// See AANoSync::isAssumedNoSync() - bool isAssumedNoSync() const override { return getAssumed(); } - - /// See AANoSync::isKnownNoSync() - bool isKnownNoSync() const override { return getKnown(); } - /// Helper function used to determine whether an instruction is non-relaxed /// atomic. In other words, if an atomic instruction does not have unordered /// or monotonic ordering @@ -969,15 +945,9 @@ /// ------------------------ No-Free Attributes ---------------------------- -struct AANoFreeImpl : public AANoFree, BooleanState { +struct AANoFreeImpl : public AANoFree { IRPositionConstructorForward(AANoFreeImpl, AANoFree); - /// See AbstractAttribute::getState() - ///{ - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - ///} - /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return getAssumed() ? "nofree" : "may-free"; @@ -985,12 +955,6 @@ /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - - /// Return true if "nofree" is assumed. - bool isAssumedNoFree() const override { return getAssumed(); } - - /// Return true if "nofree" is known. - bool isKnownNoFree() const override { return getKnown(); } }; struct AANoFreeFunction final : public AANoFreeImpl { @@ -1015,26 +979,15 @@ } /// ------------------------ NonNull Argument Attribute ------------------------ -struct AANonNullImpl : AANonNull, BooleanState { +struct AANonNullImpl : AANonNull { IRPositionConstructorForward(AANonNullImpl, AANonNull); - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return getAssumed() ? "nonnull" : "may-null"; } - /// See AANonNull::isAssumedNonNull(). - bool isAssumedNonNull() const override { return getAssumed(); } - - /// See AANonNull::isKnownNonNull(). - bool isKnownNonNull() const override { return getKnown(); } - /// Generate a predicate that checks if a given value is assumed nonnull. /// The generated function returns true if a value satisfies any of /// following conditions. @@ -1200,21 +1153,9 @@ /// ------------------------ Will-Return Attributes ---------------------------- -struct AAWillReturnImpl : public AAWillReturn, BooleanState { +struct AAWillReturnImpl : public AAWillReturn { IRPositionConstructorForward(AAWillReturnImpl, AAWillReturn); - /// See AAWillReturn::isKnownWillReturn(). - bool isKnownWillReturn() const override { return getKnown(); } - - /// See AAWillReturn::isAssumedWillReturn(). - bool isAssumedWillReturn() const override { return getAssumed(); } - - /// See AbstractAttribute::getState(...). - AbstractState &getState() override { return *this; } - - /// See AbstractAttribute::getState(...). - const AbstractState &getState() const override { return *this; } - /// See AbstractAttribute::getAsStr() const std::string getAsStr() const override { return getAssumed() ? "willreturn" : "may-noreturn"; @@ -1294,24 +1235,12 @@ /// ------------------------ NoAlias Argument Attribute ------------------------ -struct AANoAliasImpl : AANoAlias, BooleanState { +struct AANoAliasImpl : AANoAlias { IRPositionConstructorForward(AANoAliasImpl, AANoAlias); - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - const std::string getAsStr() const override { return getAssumed() ? "noalias" : "may-alias"; } - - /// See AANoAlias::isAssumedNoAlias(). - bool isAssumedNoAlias() const override { return getAssumed(); } - - /// See AANoAlias::isKnowndNoAlias(). - bool isKnownNoAlias() const override { return getKnown(); } }; /// NoAlias attribute for function return value. @@ -1374,7 +1303,7 @@ /// -------------------AAIsDead Function Attribute----------------------- -struct AAIsDeadImpl : public AAIsDead, BooleanState { +struct AAIsDeadImpl : public AAIsDead { IRPositionConstructorForward(AAIsDeadImpl, AAIsDead); void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -1513,12 +1442,6 @@ return F.hasPersonalityFn() && !canSimplifyInvokeNoUnwind(&F); } - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - /// Collection of to be explored paths. SmallSetVector ToBeExploredPaths; @@ -1697,11 +1620,12 @@ struct AADereferenceableImpl : AADereferenceable, DerefState { IRPositionConstructorForward(AADereferenceableImpl, AADereferenceable); + using StateType = DerefState; /// See AbstractAttribute::getState() /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } + StateType &getState() override { return *this; } + const StateType &getState() const override { return *this; } /// } /// See AADereferenceable::getAssumedDereferenceableBytes(). @@ -1964,30 +1888,18 @@ // ------------------------ Align Argument Attribute ------------------------ -struct AAAlignImpl : AAAlign, IntegerState { +struct AAAlignImpl : AAAlign { IRPositionConstructorForward(AAAlignImpl, AAAlign); // Max alignemnt value allowed in IR static const unsigned MAX_ALIGN = 1U << 29; - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - virtual const std::string getAsStr() const override { return getAssumedAlign() ? ("align<" + std::to_string(getKnownAlign()) + "-" + std::to_string(getAssumedAlign()) + ">") : "unknown-align"; } - /// See AAAlign::getAssumedAlign(). - unsigned getAssumedAlign() const override { return getAssumed(); } - - /// See AAAlign::getKnownAlign(). - unsigned getKnownAlign() const override { return getKnown(); } - /// See AbstractAttriubute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { takeAssumedMinimum(MAX_ALIGN); @@ -2136,21 +2048,9 @@ } /// ------------------ Function No-Return Attribute ---------------------------- -struct AANoReturnImpl : public AANoReturn, BooleanState { +struct AANoReturnImpl : public AANoReturn { IRPositionConstructorForward(AANoReturnImpl, AANoReturn); - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - - /// Return true if the underlying object is known to never return. - bool isKnownNoReturn() const override { return getKnown(); } - - /// Return true if the underlying object is assumed to never return. - bool isAssumedNoReturn() const override { return getAssumed(); } - /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return getAssumed() ? "noreturn" : "may-return";