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 @@ -60,12 +60,12 @@ // manifest their result in the IR for passes to come. // // Attribute manifestation is not mandatory. If desired, there is support to -// generate a single LLVM-IR attribute already in the AbstractAttribute base -// class. In the simplest case, a subclass initializes the IRPosition properly -// and overloads `AbstractAttribute::getAttrKind()` to return the appropriate -// value. The Attributor manifestation framework will then create and place a -// new attribute if it is allowed to do so (based on the abstract state). Other -// use cases can be achieved by overloading other abstract attribute methods. +// generate a single or multiple LLVM-IR attributes already in the helper struct +// IRAttribute. In the simplest case, a subclass inherits from IRAttribute with +// a proper Attribute::AttrKind as template parameter. The Attributor +// manifestation framework will then create and place a new attribute if it is +// allowed to do so (based on the abstract state). Other use cases can be +// achieved by overloading other abstract attribute methods. // // // The "mechanics" of adding a new "abstract attribute": @@ -544,6 +544,12 @@ "Expected a valid argument index!"); } +#define IRPositionConstructorForward(NAME, BASE) \ + explicit NAME(Argument &Arg) : BASE(Arg) {} \ + explicit NAME(Function &Fn, IRPosition::Kind PK) : BASE(Fn, PK) {} \ + NAME(Value *AssociatedVal, Value &AnchorVal, unsigned ArgumentNo) \ + : BASE(AssociatedVal, AnchorVal, ArgumentNo) {} + IRPosition(const IRPosition &AAP) : IRPosition(AAP.AssociatedVal, AAP.AnchorVal, AAP.AttributeIdx) {} @@ -627,6 +633,36 @@ int AttributeIdx; }; +/// Helper class that provides common functionality to manifest IR attributes. +template +struct IRAttribute : public IRPosition, public Base { + + /// Constructors for the IRPosition. + /// + ///{ + IRPositionConstructorForward(IRAttribute, IRPosition); + ///} + + /// See AbstractAttribute::manifest(...). + virtual ChangeStatus manifest(Attributor &A); + + /// Return the kind that identifies the abstract attribute implementation. + Attribute::AttrKind getAttrKind() const { return AK; } + + /// Return the deduced attributes in \p Attrs. + virtual void getDeducedAttributes(LLVMContext &Ctx, + SmallVectorImpl &Attrs) const { + Attrs.emplace_back(Attribute::get(Ctx, getAttrKind())); + } + + /// Return an IR position, see struct IRPosition. + /// + ///{ + IRPosition &getIRPosition() { return *this; } + const IRPosition &getIRPosition() const { return *this; } + ///} +}; + /// Base struct for all "concrete attribute" deductions. /// /// The abstract attribute is a minimal interface that allows the Attributor to @@ -691,15 +727,6 @@ /// Return an IR position, see struct IRPosition. virtual const IRPosition &getIRPosition() const = 0; - /// Return the kind that identifies the abstract attribute implementation. - virtual Attribute::AttrKind getAttrKind() const = 0; - - /// Return the deduced attributes in \p Attrs. - virtual void getDeducedAttributes(SmallVectorImpl &Attrs) const { - LLVMContext &Ctx = getIRPosition().getAnchorScope().getContext(); - Attrs.emplace_back(Attribute::get(Ctx, getAttrKind())); - } - /// Helper functions, for debug purposes only. ///{ virtual void print(raw_ostream &OS) const; @@ -725,7 +752,9 @@ /// represented by the abstract attribute in the LLVM-IR. /// /// \Return CHANGED if the IR was altered, otherwise UNCHANGED. - virtual ChangeStatus manifest(Attributor &A); + virtual ChangeStatus manifest(Attributor &A) { + return ChangeStatus::UNCHANGED; + } /// Return an IR position, see struct IRPosition. virtual IRPosition &getIRPosition() = 0; @@ -764,7 +793,9 @@ /// ---------------------------------------------------------------------------- /// An abstract attribute for the returned values of a function. -struct AAReturnedValues : public AbstractAttribute { +struct AAReturnedValues + : public IRAttribute { + IRPositionConstructorForward(AAReturnedValues, IRAttribute); /// Check \p Pred on all returned values. /// @@ -775,21 +806,12 @@ std::function &)> &Pred) const = 0; - /// See AbstractAttribute::getAttrKind() - Attribute::AttrKind getAttrKind() const override { - return Attribute::Returned; - } - /// Unique ID (due to the unique address) static const char ID; }; -struct AANoUnwind : public AbstractAttribute { - - /// See AbstractAttribute::getAttrKind()/ - Attribute::AttrKind getAttrKind() const override { - return Attribute::NoUnwind; - } +struct AANoUnwind : public IRAttribute { + IRPositionConstructorForward(AANoUnwind, IRAttribute); /// Returns true if nounwind is assumed. virtual bool isAssumedNoUnwind() const = 0; @@ -801,10 +823,8 @@ static const char ID; }; -struct AANoSync : public AbstractAttribute { - - /// See AbstractAttribute::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { return Attribute::NoSync; } +struct AANoSync : public IRAttribute { + IRPositionConstructorForward(AANoSync, IRAttribute); /// Returns true if "nosync" is assumed. virtual bool isAssumedNoSync() const = 0; @@ -817,7 +837,8 @@ }; /// An abstract interface for all nonnull attributes. -struct AANonNull : public AbstractAttribute { +struct AANonNull : public IRAttribute { + IRPositionConstructorForward(AANonNull, IRAttribute); /// Return true if we assume that the underlying value is nonnull. virtual bool isAssumedNonNull() const = 0; @@ -825,22 +846,14 @@ /// Return true if we know that underlying value is nonnull. virtual bool isKnownNonNull() const = 0; - /// See AbastractState::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { - return Attribute::NonNull; - } - /// Unique ID (due to the unique address) static const char ID; }; /// An abstract attribute for norecurse. -struct AANoRecurse : public AbstractAttribute { - - /// See AbstractAttribute::getAttrKind() - virtual Attribute::AttrKind getAttrKind() const override { - return Attribute::NoRecurse; - } +struct AANoRecurse + : public IRAttribute { + IRPositionConstructorForward(AANoRecurse, IRAttribute); /// Return true if "norecurse" is known. virtual bool isKnownNoRecurse() const = 0; @@ -853,12 +866,9 @@ }; /// An abstract attribute for willreturn. -struct AAWillReturn : public AbstractAttribute { - - /// See AbstractAttribute::getAttrKind() - virtual Attribute::AttrKind getAttrKind() const override { - return Attribute::WillReturn; - } +struct AAWillReturn + : public IRAttribute { + IRPositionConstructorForward(AAWillReturn, IRAttribute); /// Return true if "willreturn" is known. virtual bool isKnownWillReturn() const = 0; @@ -871,7 +881,8 @@ }; /// An abstract interface for all noalias attributes. -struct AANoAlias : public AbstractAttribute { +struct AANoAlias : public IRAttribute { + IRPositionConstructorForward(AANoAlias, IRAttribute); /// Return true if we assume that the underlying value is alias. virtual bool isAssumedNoAlias() const = 0; @@ -879,17 +890,27 @@ /// Return true if we know that underlying value is noalias. virtual bool isKnownNoAlias() const = 0; - /// See AbastractState::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { - return Attribute::NoAlias; - } + /// Unique ID (due to the unique address) + static const char ID; +}; + +/// An AbstractAttribute for nofree. +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; /// Unique ID (due to the unique address) static const char ID; }; /// An AbstractAttribute for noreturn. -struct AANoReturn : public AbstractAttribute { +struct AANoReturn : public IRAttribute { + IRPositionConstructorForward(AANoReturn, IRAttribute); /// Return true if the underlying object is known to never return. virtual bool isKnownNoReturn() const = 0; @@ -897,20 +918,13 @@ /// Return true if the underlying object is assumed to never return. virtual bool isAssumedNoReturn() const = 0; - /// See AbstractAttribute::getAttrKind() - Attribute::AttrKind getAttrKind() const override { - return Attribute::NoReturn; - } - /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for liveness abstract attribute. -struct AAIsDead : public AbstractAttribute { - - /// See AbstractAttribute::getAttrKind() - Attribute::AttrKind getAttrKind() const override { return Attribute::None; } +struct AAIsDead : public AbstractAttribute, public IRPosition { + IRPositionConstructorForward(AAIsDead, IRPosition); /// Returns true if \p BB is assumed dead. virtual bool isAssumedDead(const BasicBlock *BB) const = 0; @@ -938,12 +952,21 @@ return false; } + /// Return an IR position, see struct IRPosition. + /// + ///{ + IRPosition &getIRPosition() { return *this; } + const IRPosition &getIRPosition() const { return *this; } + ///} + /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for all dereferenceable attribute. -struct AADereferenceable : public AbstractAttribute { +struct AADereferenceable + : public IRAttribute { + IRPositionConstructorForward(AADereferenceable, IRAttribute); /// Return true if we assume that the underlying value is nonnull. virtual bool isAssumedNonNull() const = 0; @@ -965,17 +988,13 @@ /// Return known dereferenceable bytes. virtual uint32_t getKnownDereferenceableBytes() const = 0; - /// See AbastractState::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { - return Attribute::Dereferenceable; - } - /// Unique ID (due to the unique address) static const char ID; }; /// An abstract interface for all align attributes. -struct AAAlign : public AbstractAttribute { +struct AAAlign : public IRAttribute { + IRPositionConstructorForward(AAAlign, IRAttribute); /// Return assumed alignment. virtual unsigned getAssumedAlign() const = 0; @@ -983,11 +1002,6 @@ /// Return known alignemnt. virtual unsigned getKnownAlign() const = 0; - /// See AbastractState::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { - return Attribute::Alignment; - } - /// 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 @@ -331,21 +331,21 @@ return HasChanged; } -ChangeStatus AbstractAttribute::manifest(Attributor &A) { - assert(getState().isValidState() && +template +ChangeStatus IRAttribute::manifest(Attributor &A) { + assert(this->getState().isValidState() && "Attempted to manifest an invalid state!"); assert(getIRPosition().getAssociatedValue() && "Attempted to manifest an attribute without associated value!"); ChangeStatus HasChanged = ChangeStatus::UNCHANGED; - IRPosition &Pos = getIRPosition(); - Function &ScopeFn = Pos.getAnchorScope(); + Function &ScopeFn = getAnchorScope(); LLVMContext &Ctx = ScopeFn.getContext(); - IRPosition::Kind PK = Pos.getPositionKind(); + IRPosition::Kind PK = getPositionKind(); SmallVector DeducedAttrs; - getDeducedAttributes(DeducedAttrs); + getDeducedAttributes(Ctx, DeducedAttrs); // In the following some generic code that will manifest attributes in // DeducedAttrs if they improve the current IR. Due to the different @@ -359,12 +359,12 @@ Attrs = ScopeFn.getAttributes(); break; case IRPosition::IRP_CALL_SITE_ARGUMENT: - Attrs = ImmutableCallSite(&Pos.getAnchorValue()).getAttributes(); + Attrs = ImmutableCallSite(&getAnchorValue()).getAttributes(); break; } for (const Attribute &Attr : DeducedAttrs) { - if (!addIfNotExistent(Ctx, Attr, Attrs, Pos.getAttrIdx())) + if (!addIfNotExistent(Ctx, Attr, Attrs, getAttrIdx())) continue; HasChanged = ChangeStatus::CHANGED; @@ -381,7 +381,7 @@ ScopeFn.setAttributes(Attrs); break; case IRPosition::IRP_CALL_SITE_ARGUMENT: - CallSite(&Pos.getAnchorValue()).setAttributes(Attrs); + CallSite(&getAnchorValue()).setAttributes(Attrs); } return HasChanged; @@ -389,18 +389,8 @@ /// -----------------------NoUnwind Function Attribute-------------------------- -#define IRPositionConstructorForward(NAME) \ - NAME(Argument &Arg) : IRPosition(Arg) {} \ - NAME(Function &Fn, IRPosition::Kind PK) : IRPosition(Fn, PK) {} \ - NAME(Value *AssociatedVal, Value &AnchorVal, unsigned ArgumentNo) \ - : IRPosition(AssociatedVal, AnchorVal, ArgumentNo) {} -#define IRPositionGetter(IRP) \ - IRPosition &getIRPosition() override { return IRP; } \ - const IRPosition &getIRPosition() const override { return IRP; } - -struct AANoUnwindImpl : AANoUnwind, BooleanState, IRPosition { - IRPositionConstructorForward(AANoUnwindImpl); - IRPositionGetter(*this); +struct AANoUnwindImpl : AANoUnwind, BooleanState { + IRPositionConstructorForward(AANoUnwindImpl, AANoUnwind); /// See AbstractAttribute::getState() /// { @@ -464,9 +454,7 @@ /// /// If there is a unique returned value R, the manifest method will: /// - mark R with the "returned" attribute, if R is an argument. -class AAReturnedValuesImpl : public AAReturnedValues, - public AbstractState, - public IRPosition { +class AAReturnedValuesImpl : public AAReturnedValues, public AbstractState { /// Mapping of values potentially returned by the associated function to the /// return instructions that might return them. @@ -503,8 +491,7 @@ } public: - IRPositionConstructorForward(AAReturnedValuesImpl); - IRPositionGetter(*this); + IRPositionConstructorForward(AAReturnedValuesImpl, AAReturnedValues); /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -620,7 +607,7 @@ if (auto *UniqueRVArg = dyn_cast(UniqueRV.getValue())) { setAssociatedValue(UniqueRVArg); setAttributeIdx(UniqueRVArg->getArgNo() + AttributeList::FirstArgIndex); - Changed = AbstractAttribute::manifest(A) | Changed; + Changed = IRAttribute::manifest(A) | Changed; } return Changed; @@ -820,9 +807,8 @@ /// ------------------------ NoSync Function Attribute ------------------------- -struct AANoSyncImpl : AANoSync, BooleanState, IRPosition { - IRPositionConstructorForward(AANoSyncImpl); - IRPositionGetter(*this); +struct AANoSyncImpl : AANoSync, BooleanState { + IRPositionConstructorForward(AANoSyncImpl, AANoSync); /// See AbstractAttribute::getState() /// { @@ -1010,9 +996,8 @@ /// ------------------------ No-Free Attributes ---------------------------- -struct AANoFreeImpl : AbstractAttribute, BooleanState, IRPosition { - IRPositionConstructorForward(AANoFreeImpl); - IRPositionGetter(*this); +struct AANoFreeImpl : public AANoFree, BooleanState { + IRPositionConstructorForward(AANoFreeImpl, AANoFree); /// See AbstractAttribute::getState() ///{ @@ -1028,17 +1013,11 @@ /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - /// See AbstractAttribute::getAttrKind(). - Attribute::AttrKind getAttrKind() const override { return Attribute::NoFree; } - /// Return true if "nofree" is assumed. - bool isAssumedNoFree() const { return getAssumed(); } + bool isAssumedNoFree() const override { return getAssumed(); } /// Return true if "nofree" is known. - bool isKnownNoFree() const { return getKnown(); } - - /// Unique ID (due to the unique address) - static const char ID; + bool isKnownNoFree() const override { return getKnown(); } }; struct AANoFreeFunction final : public AANoFreeImpl { @@ -1073,9 +1052,8 @@ } /// ------------------------ NonNull Argument Attribute ------------------------ -struct AANonNullImpl : AANonNull, BooleanState, IRPosition { - IRPositionConstructorForward(AANonNullImpl); - IRPositionGetter(*this); +struct AANonNullImpl : AANonNull, BooleanState { + IRPositionConstructorForward(AANonNullImpl, AANonNull); /// See AbstractAttribute::getState() /// { @@ -1259,9 +1237,8 @@ /// ------------------------ Will-Return Attributes ---------------------------- -struct AAWillReturnImpl : public AAWillReturn, BooleanState, IRPosition { - IRPositionConstructorForward(AAWillReturnImpl); - IRPositionGetter(*this); +struct AAWillReturnImpl : public AAWillReturn, BooleanState { + IRPositionConstructorForward(AAWillReturnImpl, AAWillReturn); /// See AAWillReturn::isKnownWillReturn(). bool isKnownWillReturn() const override { return getKnown(); } @@ -1366,9 +1343,8 @@ /// ------------------------ NoAlias Argument Attribute ------------------------ -struct AANoAliasImpl : AANoAlias, BooleanState, IRPosition { - IRPositionConstructorForward(AANoAliasImpl); - IRPositionGetter(*this); +struct AANoAliasImpl : AANoAlias, BooleanState { + IRPositionConstructorForward(AANoAliasImpl, AANoAlias); /// See AbstractAttribute::getState() /// { @@ -1452,9 +1428,8 @@ /// -------------------AAIsDead Function Attribute----------------------- -struct AAIsDeadImpl : public AAIsDead, BooleanState, IRPosition { - IRPositionConstructorForward(AAIsDeadImpl); - IRPositionGetter(*this); +struct AAIsDeadImpl : public AAIsDead, BooleanState { + IRPositionConstructorForward(AAIsDeadImpl, AAIsDead); void initialize(Attributor &A, InformationCache &InfoCache) override { Function &F = getAnchorScope(); @@ -1739,9 +1714,8 @@ } }; -struct AADereferenceableImpl : AADereferenceable, DerefState, IRPosition { - IRPositionConstructorForward(AADereferenceableImpl); - IRPositionGetter(*this); +struct AADereferenceableImpl : AADereferenceable, DerefState { + IRPositionConstructorForward(AADereferenceableImpl, AADereferenceable); /// See AbstractAttribute::getState() /// { @@ -1793,9 +1767,8 @@ return NonNullGlobalState.isKnown(DEREF_NONNULL); } - void getDeducedAttributes(SmallVectorImpl &Attrs) const override { - LLVMContext &Ctx = AnchorVal.getContext(); - + void getDeducedAttributes(LLVMContext &Ctx, + SmallVectorImpl &Attrs) const override { // TODO: Add *_globally support if (isAssumedNonNull()) Attrs.emplace_back(Attribute::getWithDereferenceableBytes( @@ -2016,9 +1989,8 @@ // ------------------------ Align Argument Attribute ------------------------ -struct AAAlignImpl : AAAlign, IntegerState, IRPosition { - IRPositionConstructorForward(AAAlignImpl); - IRPositionGetter(*this); +struct AAAlignImpl : AAAlign, IntegerState { + IRPositionConstructorForward(AAAlignImpl, AAAlign); // Max alignemnt value allowed in IR static const unsigned MAX_ALIGN = 1U << 29; @@ -2057,9 +2029,8 @@ /// See AbstractAttribute::getDeducedAttributes virtual void - getDeducedAttributes(SmallVectorImpl &Attrs) const override { - LLVMContext &Ctx = AnchorVal.getContext(); - + getDeducedAttributes(LLVMContext &Ctx, + SmallVectorImpl &Attrs) const override { Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign())); } }; @@ -2193,9 +2164,8 @@ } /// ------------------ Function No-Return Attribute ---------------------------- -struct AANoReturnImpl : public AANoReturn, BooleanState, IRPosition { - IRPositionConstructorForward(AANoReturnImpl); - IRPositionGetter(*this); +struct AANoReturnImpl : public AANoReturn, BooleanState { + IRPositionConstructorForward(AANoReturnImpl, AANoReturn); /// See AbstractAttribute::getState() /// { @@ -2680,7 +2650,7 @@ const char AAReturnedValues::ID = 0; const char AANoUnwind::ID = 0; const char AANoSync::ID = 0; -const char AANoFreeImpl::ID = 0; +const char AANoFree::ID = 0; const char AANonNull::ID = 0; const char AANoRecurse::ID = 0; const char AAWillReturn::ID = 0;