From 344d038960c4e5f7a6898586dfe9cf9cad614a87 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Wed, 7 Aug 2019 22:34:26 +0000 Subject: [PATCH] [Attributor] Introduce a state wrapper class Summary: The wrapper reduces boilerplate code and also provide a nice way to determine the state type used by an abstract attributes statically via AAType::StateType. This was already discussed as part of the review of D65711. Reviewers: sstefan1, uenoku Subscribers: hiraditya, bollu, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65786 llvm-svn: 368224 --- llvm/include/llvm/Transforms/IPO/Attributor.h | 109 +++++++++++++--------- llvm/lib/Transforms/IPO/Attributor.cpp | 124 +++----------------------- 2 files changed, 81 insertions(+), 152 deletions(-) diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h index 78c74e0..e8ebcdd 100644 --- a/llvm/include/llvm/Transforms/IPO/Attributor.h +++ b/llvm/include/llvm/Transforms/IPO/Attributor.h @@ -690,6 +690,19 @@ struct IRAttributeManifest { const ArrayRef &DeducedAttrs); }; +/// 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, public IRAttributeManifest { @@ -769,6 +782,7 @@ struct IRAttribute : public IRPosition, public Base, public IRAttributeManifest /// 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() {} @@ -784,7 +798,8 @@ struct AbstractAttribute { 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; @@ -820,9 +835,6 @@ protected: /// 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. /// @@ -875,41 +887,47 @@ struct AAReturnedValues 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; @@ -917,14 +935,15 @@ struct AANonNull : public IRAttribute { /// 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; @@ -932,63 +951,71 @@ struct AANoRecurse /// 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; + bool isAssumedWillReturn() const { return getAssumed(); } + + /// Return true if "willreturn" is known. + 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. @@ -1058,14 +1085,16 @@ struct AADereferenceable }; /// 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 index 2cc140a..b3c1223 100644 --- a/llvm/lib/Transforms/IPO/Attributor.cpp +++ b/llvm/lib/Transforms/IPO/Attributor.cpp @@ -385,27 +385,15 @@ ChangeStatus AbstractAttribute::update(Attributor &A, /// -----------------------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 { @@ -787,15 +775,9 @@ ChangeStatus AAReturnedValuesImpl::updateImpl(Attributor &A, /// ------------------------ 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"; } @@ -803,12 +785,6 @@ struct AANoSyncImpl : AANoSync, BooleanState { /// 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 @@ -962,15 +938,9 @@ ChangeStatus AANoSyncImpl::updateImpl(Attributor &A, /// ------------------------ 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"; @@ -978,12 +948,6 @@ struct AANoFreeImpl : public AANoFree, BooleanState { /// 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 { @@ -1008,26 +972,15 @@ ChangeStatus AANoFreeImpl::updateImpl(Attributor &A, } /// ------------------------ 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. @@ -1189,21 +1142,9 @@ AANonNullCallSiteArgument::updateImpl(Attributor &A, /// ------------------------ 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"; @@ -1283,24 +1224,12 @@ ChangeStatus AAWillReturnFunction::updateImpl(Attributor &A, /// ------------------------ 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. @@ -1363,7 +1292,7 @@ ChangeStatus AANoAliasReturned::updateImpl(Attributor &A, /// -------------------AAIsDead Function Attribute----------------------- -struct AAIsDeadImpl : public AAIsDead, BooleanState { +struct AAIsDeadImpl : public AAIsDead { IRPositionConstructorForward(AAIsDeadImpl, AAIsDead); void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -1502,12 +1431,6 @@ struct AAIsDeadImpl : public AAIsDead, BooleanState { 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; @@ -1696,11 +1619,12 @@ struct DerefState : AbstractState { 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(). @@ -1963,30 +1887,18 @@ AADereferenceableCallSiteArgument::updateImpl(Attributor &A, // ------------------------ 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); @@ -2135,21 +2047,9 @@ ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A, } /// ------------------ 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"; -- 2.7.4