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 @@ -61,12 +61,11 @@ // // 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 overloads -// `AbstractAttribute::getManifestPosition()` and -// `AbstractAttribute::getAttrKind()` to return the appropriate values. 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. +// 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. // // // The "mechanics" of adding a new "abstract attribute": @@ -233,14 +232,14 @@ // lookup the attribute together with AAType::ID. If passed an argument, // use its argument number but do not override a given one as it could be a // use of the argument at a call site. - Value &AnchoredVal = AA.getAnchoredValue(); + Value &AnchorVal = AA.getIRPosition().getAnchorValue(); if (ArgNo == -1) - if (auto *Arg = dyn_cast(&AnchoredVal)) + if (auto *Arg = dyn_cast(&AnchorVal)) ArgNo = Arg->getArgNo(); // Put the attribute in the lookup map structure and the container we use to // keep track of all attributes. - AAMap[{&AnchoredVal, ArgNo}][&AAType::ID] = &AA; + AAMap[{&AnchorVal, ArgNo}][&AAType::ID] = &AA; AllAbstractAttributes.push_back(&AA); return AA; } @@ -498,6 +497,136 @@ BooleanState() : IntegerState(1){}; }; +/// Struct to encode the position in the LLVM-IR with regards to the associated +/// value but also the attribute lists. +struct IRPosition { + + /// The positions attributes can be manifested in. + enum Kind { + IRP_FUNCTION = AttributeList::FunctionIndex, ///< An attribute for a + ///< function as a whole. + IRP_RETURNED = AttributeList::ReturnIndex, ///< An attribute for the + ///< function return value. + IRP_ARGUMENT, ///< An attribute for a function argument. + IRP_CALL_SITE_ARGUMENT, ///< An attribute for a call site argument. + }; + + /// Create an IRPosition for an argument. + explicit IRPosition(Argument &Arg) : IRPosition(&Arg, Arg, Arg.getArgNo()) {} + + /// Create an IRPosition for a function return or function body position. + /// + /// \param Fn The value this abstract attributes is anchored at and + /// associated with. + /// \param PK The kind of attribute position, can not be a (call site) + /// argument. + explicit IRPosition(Function &Fn, Kind PK) + : AssociatedVal(&Fn), AnchorVal(Fn), AttributeIdx(PK) { + assert((PK == IRP_RETURNED || PK == IRP_FUNCTION) && + "Expected non-argument position!"); + } + + /// An abstract attribute associated with \p AssociatedVal and anchored at + /// \p AnchorVal. + /// + /// \param AssociatedVal The value this abstract attribute is associated with. + /// \param AnchorVal The value this abstract attributes is anchored at. + /// \param ArgumentNo The index in the attribute list, encodes also the + /// argument number if this is one. + explicit IRPosition(Value *AssociatedVal, Value &AnchorVal, + unsigned ArgumentNo) + : AssociatedVal(AssociatedVal), AnchorVal(AnchorVal), + AttributeIdx(ArgumentNo + AttributeList::FirstArgIndex) { + assert(((isa(&AnchorVal) && + cast(&AnchorVal)->arg_size() > ArgumentNo) || + (isa(AnchorVal) && + cast(AnchorVal).getArgNo() == ArgumentNo)) && + "Expected a valid argument index!"); + } + + IRPosition(const IRPosition &AAP) + : IRPosition(AAP.AssociatedVal, AAP.AnchorVal, AAP.AttributeIdx) {} + + /// Virtual destructor. + virtual ~IRPosition() {} + + /// Return the value this abstract attribute is anchored with. + /// + /// The anchored value might not be the associated value if the latter is not + /// sufficient to determine where arguments will be manifested. This is mostly + /// the case for call site arguments as the value is not sufficient to + /// pinpoint them. Instead, we can use the call site as an anchor. + /// + ///{ + Value &getAnchorValue() { return AnchorVal; } + const Value &getAnchorValue() const { return AnchorVal; } + ///} + + /// Return the llvm::Function surrounding the anchored value. + /// + ///{ + Function &getAnchorScope() { + Value &V = getAnchorValue(); + if (isa(V)) + return cast(V); + if (isa(V)) + return *cast(V).getParent(); + if (isa(V)) + return *cast(V).getFunction(); + llvm_unreachable("No scope for anchored value found!"); + } + const Function &getAnchorScope() const { + return const_cast(this)->getAnchorScope(); + } + ///} + + /// Return the value this abstract attribute is associated with. + /// + /// The abstract state usually represents this value. + /// + ///{ + Value *getAssociatedValue() { return AssociatedVal; } + const Value *getAssociatedValue() const { return AssociatedVal; } + ///} + + /// Return the argument number of the associated value if it is an argument or + /// call site argument, otherwise a negative value. + int getArgNo() const { return AttributeIdx - AttributeList::FirstArgIndex; } + + /// Return the position this abstract state is manifested in. + Kind getPositionKind() const { + if (getArgNo() >= 0) { + if (isa(getAnchorValue())) + return IRP_CALL_SITE_ARGUMENT; + assert((isa(getAnchorValue()) || + isa_and_nonnull(getAssociatedValue()) || + (!getAssociatedValue() && isa(getAnchorValue()))) && + "Expected argument or call base due to argument number!"); + return IRP_ARGUMENT; + } + return (Kind)AttributeIdx; + } + + /// Return the index in the attribute list for this position. + int getAttrIdx() const { return AttributeIdx; } + + /// Change the associated value. + void setAssociatedValue(Value *V) { AssociatedVal = V; } + + /// Change the associated attribue list position. + void setAttributeIdx(int AttrIdx) { AttributeIdx = AttrIdx; } + +protected: + /// The value this abstract attribute is associated with. + Value *AssociatedVal; + + /// The value this abstract attribute is anchored at. + Value &AnchorVal; + + /// The index in the attribute list. + int AttributeIdx; +}; + /// Base struct for all "concrete attribute" deductions. /// /// The abstract attribute is a minimal interface that allows the Attributor to @@ -543,25 +672,6 @@ /// described in the file comment. struct AbstractAttribute { - /// The positions attributes can be manifested in. - enum ManifestPosition { - MP_ARGUMENT, ///< An attribute for a function argument. - MP_CALL_SITE_ARGUMENT, ///< An attribute for a call site argument. - MP_FUNCTION, ///< An attribute for a function as a whole. - MP_RETURNED, ///< An attribute for the function return value. - }; - - /// An abstract attribute associated with \p AssociatedVal and anchored at - /// \p AnchoredVal. - /// - /// \param AssociatedVal The value this abstract attribute is associated with. - /// \param AnchoredVal The value this abstract attributes is anchored at. - AbstractAttribute(Value *AssociatedVal, Value &AnchoredVal) - : AssociatedVal(AssociatedVal), AnchoredVal(AnchoredVal) {} - - /// An abstract attribute associated with and anchored at \p V. - AbstractAttribute(Value &V) : AbstractAttribute(&V, V) {} - /// Virtual destructor. virtual ~AbstractAttribute() {} @@ -578,43 +688,15 @@ /// Return the internal abstract state for inspection. virtual const AbstractState &getState() const = 0; - /// Return the value this abstract attribute is anchored with. - /// - /// The anchored value might not be the associated value if the latter is not - /// sufficient to determine where arguments will be manifested. This is mostly - /// the case for call site arguments as the value is not sufficient to - /// pinpoint them. Instead, we can use the call site as an anchor. - /// - ///{ - Value &getAnchoredValue() { return AnchoredVal; } - const Value &getAnchoredValue() const { return AnchoredVal; } - ///} - - /// Return the llvm::Function surrounding the anchored value. - /// - ///{ - Function &getAnchorScope(); - const Function &getAnchorScope() const; - ///} - - /// Return the value this abstract attribute is associated with. - /// - /// The abstract state usually represents this value. - /// - ///{ - virtual Value *getAssociatedValue() { return AssociatedVal; } - virtual const Value *getAssociatedValue() const { return AssociatedVal; } - ///} - - /// Return the position this abstract state is manifested in. - virtual ManifestPosition getManifestPosition() const = 0; + /// 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 = AnchoredVal.getContext(); + LLVMContext &Ctx = getIRPosition().getAnchorScope().getContext(); Attrs.emplace_back(Attribute::get(Ctx, getAttrKind())); } @@ -644,6 +726,8 @@ /// /// \Return CHANGED if the IR was altered, otherwise UNCHANGED. virtual ChangeStatus manifest(Attributor &A); + /// Return an IR position, see struct IRPosition. + virtual IRPosition &getIRPosition() = 0; /// Return the internal abstract state for careful modification. virtual AbstractState &getState() = 0; @@ -657,12 +741,6 @@ /// \Return CHANGED if the internal state changed, otherwise UNCHANGED. virtual ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) = 0; - - /// The value this abstract attribute is associated with. - Value *AssociatedVal; - - /// The value this abstract attribute is anchored at. - Value &AnchoredVal; }; /// Forward declarations of output streams for debug purposes. @@ -670,7 +748,8 @@ ///{ raw_ostream &operator<<(raw_ostream &OS, const AbstractAttribute &AA); raw_ostream &operator<<(raw_ostream &OS, ChangeStatus S); -raw_ostream &operator<<(raw_ostream &OS, AbstractAttribute::ManifestPosition); +raw_ostream &operator<<(raw_ostream &OS, IRPosition::Kind); +raw_ostream &operator<<(raw_ostream &OS, const IRPosition &); raw_ostream &operator<<(raw_ostream &OS, const AbstractState &State); ///} @@ -686,8 +765,6 @@ /// An abstract attribute for the returned values of a function. struct AAReturnedValues : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AAReturnedValues(Function &F) : AbstractAttribute(F) {} /// Check \p Pred on all returned values. /// @@ -708,8 +785,6 @@ }; struct AANoUnwind : public AbstractAttribute { - /// An abstract interface for all nosync attributes. - AANoUnwind(Value &V) : AbstractAttribute(V) {} /// See AbstractAttribute::getAttrKind()/ Attribute::AttrKind getAttrKind() const override { @@ -727,8 +802,6 @@ }; struct AANoSync : public AbstractAttribute { - /// An abstract interface for all nosync attributes. - AANoSync(Value &V) : AbstractAttribute(V) {} /// See AbstractAttribute::getAttrKind(). Attribute::AttrKind getAttrKind() const override { return Attribute::NoSync; } @@ -746,13 +819,6 @@ /// An abstract interface for all nonnull attributes. struct AANonNull : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AANonNull(Value &V) : AbstractAttribute(V) {} - - /// See AbstractAttribute::AbstractAttribute(...). - AANonNull(Value *AssociatedVal, Value &AnchoredValue) - : AbstractAttribute(AssociatedVal, AnchoredValue) {} - /// Return true if we assume that the underlying value is nonnull. virtual bool isAssumedNonNull() const = 0; @@ -771,9 +837,6 @@ /// An abstract attribute for norecurse. struct AANoRecurse : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AANoRecurse(Value &V) : AbstractAttribute(V) {} - /// See AbstractAttribute::getAttrKind() virtual Attribute::AttrKind getAttrKind() const override { return Attribute::NoRecurse; @@ -792,9 +855,6 @@ /// An abstract attribute for willreturn. struct AAWillReturn : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AAWillReturn(Value &V) : AbstractAttribute(V) {} - /// See AbstractAttribute::getAttrKind() virtual Attribute::AttrKind getAttrKind() const override { return Attribute::WillReturn; @@ -813,9 +873,6 @@ /// An abstract interface for all noalias attributes. struct AANoAlias : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AANoAlias(Value &V) : AbstractAttribute(V) {} - /// Return true if we assume that the underlying value is alias. virtual bool isAssumedNoAlias() const = 0; @@ -834,9 +891,6 @@ /// An AbstractAttribute for noreturn. struct AANoReturn : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AANoReturn(Value &V) : AbstractAttribute(V) {} - /// Return true if the underlying object is known to never return. virtual bool isKnownNoReturn() const = 0; @@ -855,9 +909,6 @@ /// An abstract interface for liveness abstract attribute. struct AAIsDead : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AAIsDead(Value &V) : AbstractAttribute(V) {} - /// See AbstractAttribute::getAttrKind() Attribute::AttrKind getAttrKind() const override { return Attribute::None; } @@ -877,7 +928,7 @@ /// of instructions is live. template bool isLiveInstSet(T begin, T end) const { for (const auto &I : llvm::make_range(begin, end)) { - assert(I->getFunction() == &getAnchorScope() && + assert(I->getFunction() == &getIRPosition().getAnchorScope() && "Instruction must be in the same anchor scope function."); if (!isAssumedDead(I)) @@ -894,13 +945,6 @@ /// An abstract interface for all dereferenceable attribute. struct AADereferenceable : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AADereferenceable(Value &V) : AbstractAttribute(V) {} - - /// See AbstractAttribute::AbstractAttribute(...). - AADereferenceable(Value *AssociatedVal, Value &AnchoredValue) - : AbstractAttribute(AssociatedVal, AnchoredValue) {} - /// Return true if we assume that the underlying value is nonnull. virtual bool isAssumedNonNull() const = 0; @@ -933,24 +977,17 @@ /// An abstract interface for all align attributes. struct AAAlign : public AbstractAttribute { - /// See AbstractAttribute::AbstractAttribute(...). - AAAlign(Value &V) : AbstractAttribute(V) {} + /// Return assumed alignment. + virtual unsigned getAssumedAlign() const = 0; - /// See AbstractAttribute::AbstractAttribute(...). - AAAlign(Value *AssociatedVal, Value &AnchoredValue) - : AbstractAttribute(AssociatedVal, AnchoredValue) {} + /// Return known alignemnt. + virtual unsigned getKnownAlign() const = 0; /// See AbastractState::getAttrKind(). Attribute::AttrKind getAttrKind() const override { return Attribute::Alignment; } - /// Return assumed alignment. - virtual unsigned getAssumedAlign() const = 0; - - /// Return known alignemnt. - virtual unsigned getKnownAlign() const = 0; - /// 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 @@ -113,21 +113,20 @@ ///} /// Helper to adjust the statistics. -static void bookkeeping(AbstractAttribute::ManifestPosition MP, - const Attribute &Attr) { +static void bookkeeping(IRPosition::Kind PK, const Attribute &Attr) { if (!AreStatisticsEnabled()) return; switch (Attr.getKindAsEnum()) { case Attribute::Alignment: - switch (MP) { - case AbstractAttribute::MP_RETURNED: + switch (PK) { + case IRPosition::IRP_RETURNED: NumFnReturnedAlign++; break; - case AbstractAttribute::MP_ARGUMENT: + case IRPosition::IRP_ARGUMENT: NumFnArgumentAlign++; break; - case AbstractAttribute::MP_CALL_SITE_ARGUMENT: + case IRPosition::IRP_CALL_SITE_ARGUMENT: NumCSArgumentAlign++; break; default: @@ -135,14 +134,14 @@ } break; case Attribute::Dereferenceable: - switch (MP) { - case AbstractAttribute::MP_RETURNED: + switch (PK) { + case IRPosition::IRP_RETURNED: NumFnReturnedDereferenceable++; break; - case AbstractAttribute::MP_ARGUMENT: + case IRPosition::IRP_ARGUMENT: NumFnArgumentDereferenceable++; break; - case AbstractAttribute::MP_CALL_SITE_ARGUMENT: + case IRPosition::IRP_CALL_SITE_ARGUMENT: NumCSArgumentDereferenceable++; break; default: @@ -162,14 +161,14 @@ NumFnNoFree++; break; case Attribute::NonNull: - switch (MP) { - case AbstractAttribute::MP_RETURNED: + switch (PK) { + case IRPosition::IRP_RETURNED: NumFnReturnedNonNull++; break; - case AbstractAttribute::MP_ARGUMENT: + case IRPosition::IRP_ARGUMENT: NumFnArgumentNonNull++; break; - case AbstractAttribute::MP_CALL_SITE_ARGUMENT: + case IRPosition::IRP_CALL_SITE_ARGUMENT: NumCSArgumentNonNull++; break; default: @@ -273,21 +272,6 @@ return true; } -/// Helper to identify the correct offset into an attribute list. -static unsigned getAttrIndex(AbstractAttribute::ManifestPosition MP, - unsigned ArgNo = 0) { - switch (MP) { - case AbstractAttribute::MP_ARGUMENT: - case AbstractAttribute::MP_CALL_SITE_ARGUMENT: - return ArgNo + AttributeList::FirstArgIndex; - case AbstractAttribute::MP_FUNCTION: - return AttributeList::FunctionIndex; - case AbstractAttribute::MP_RETURNED: - return AttributeList::ReturnIndex; - } - llvm_unreachable("Unknown manifest position!"); -} - /// Return true if \p New is equal or worse than \p Old. static bool isEqualOrWorse(const Attribute &New, const Attribute &Old) { if (!Old.isIntAttribute()) @@ -298,12 +282,9 @@ /// Return true if the information provided by \p Attr was added to the /// attribute list \p Attrs. This is only the case if it was not already present -/// in \p Attrs at the position describe by \p MP and \p ArgNo. +/// in \p Attrs at the position describe by \p PK and \p AttrIdx. static bool addIfNotExistent(LLVMContext &Ctx, const Attribute &Attr, - AttributeList &Attrs, - AbstractAttribute::ManifestPosition MP, - unsigned ArgNo = 0) { - unsigned AttrIdx = getAttrIndex(MP, ArgNo); + AttributeList &Attrs, int AttrIdx) { if (Attr.isEnumAttribute()) { Attribute::AttrKind Kind = Attr.getKindAsEnum(); @@ -353,98 +334,73 @@ ChangeStatus AbstractAttribute::manifest(Attributor &A) { assert(getState().isValidState() && "Attempted to manifest an invalid state!"); - assert(getAssociatedValue() && + assert(getIRPosition().getAssociatedValue() && "Attempted to manifest an attribute without associated value!"); ChangeStatus HasChanged = ChangeStatus::UNCHANGED; - SmallVector DeducedAttrs; - getDeducedAttributes(DeducedAttrs); - Function &ScopeFn = getAnchorScope(); + IRPosition &Pos = getIRPosition(); + Function &ScopeFn = Pos.getAnchorScope(); LLVMContext &Ctx = ScopeFn.getContext(); - ManifestPosition MP = getManifestPosition(); + IRPosition::Kind PK = Pos.getPositionKind(); - AttributeList Attrs; - SmallVector ArgNos; + SmallVector DeducedAttrs; + getDeducedAttributes(DeducedAttrs); // In the following some generic code that will manifest attributes in // DeducedAttrs if they improve the current IR. Due to the different // annotation positions we use the underlying AttributeList interface. - // Note that MP_CALL_SITE_ARGUMENT can annotate multiple locations. - switch (MP) { - case MP_ARGUMENT: - ArgNos.push_back(cast(getAssociatedValue())->getArgNo()); + AttributeList Attrs; + switch (PK) { + case IRPosition::IRP_ARGUMENT: + case IRPosition::IRP_FUNCTION: + case IRPosition::IRP_RETURNED: Attrs = ScopeFn.getAttributes(); break; - case MP_FUNCTION: - case MP_RETURNED: - ArgNos.push_back(0); - Attrs = ScopeFn.getAttributes(); + case IRPosition::IRP_CALL_SITE_ARGUMENT: + Attrs = ImmutableCallSite(&Pos.getAnchorValue()).getAttributes(); break; - case MP_CALL_SITE_ARGUMENT: { - CallSite CS(&getAnchoredValue()); - for (unsigned u = 0, e = CS.getNumArgOperands(); u != e; u++) - if (CS.getArgOperand(u) == getAssociatedValue()) - ArgNos.push_back(u); - Attrs = CS.getAttributes(); - } } for (const Attribute &Attr : DeducedAttrs) { - for (unsigned ArgNo : ArgNos) { - if (!addIfNotExistent(Ctx, Attr, Attrs, MP, ArgNo)) - continue; + if (!addIfNotExistent(Ctx, Attr, Attrs, Pos.getAttrIdx())) + continue; - HasChanged = ChangeStatus::CHANGED; - bookkeeping(MP, Attr); - } + HasChanged = ChangeStatus::CHANGED; + bookkeeping(PK, Attr); } if (HasChanged == ChangeStatus::UNCHANGED) return HasChanged; - switch (MP) { - case MP_ARGUMENT: - case MP_FUNCTION: - case MP_RETURNED: + switch (PK) { + case IRPosition::IRP_ARGUMENT: + case IRPosition::IRP_FUNCTION: + case IRPosition::IRP_RETURNED: ScopeFn.setAttributes(Attrs); break; - case MP_CALL_SITE_ARGUMENT: - CallSite(&getAnchoredValue()).setAttributes(Attrs); + case IRPosition::IRP_CALL_SITE_ARGUMENT: + CallSite(&Pos.getAnchorValue()).setAttributes(Attrs); } return HasChanged; } -Function &AbstractAttribute::getAnchorScope() { - Value &V = getAnchoredValue(); - if (isa(V)) - return cast(V); - if (isa(V)) - return *cast(V).getParent(); - if (isa(V)) - return *cast(V).getFunction(); - llvm_unreachable("No scope for anchored value found!"); -} - -const Function &AbstractAttribute::getAnchorScope() const { - return const_cast(this)->getAnchorScope(); -} - -// Helper function that returns argument index of value. -// If the value is not an argument, this returns -1. -static int getArgNo(Value &V) { - if (auto *Arg = dyn_cast(&V)) - return Arg->getArgNo(); - return -1; -} - /// -----------------------NoUnwind Function Attribute-------------------------- -struct AANoUnwindFunction : AANoUnwind, BooleanState { +#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; } - AANoUnwindFunction(Function &F) : AANoUnwind(F) {} +struct AANoUnwindImpl : AANoUnwind, BooleanState, IRPosition { + IRPositionConstructorForward(AANoUnwindImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -452,9 +408,6 @@ const AbstractState &getState() const override { return *this; } /// } - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } - const std::string getAsStr() const override { return getAssumed() ? "nounwind" : "may-unwind"; } @@ -469,8 +422,12 @@ bool isKnownNoUnwind() const override { return getKnown(); } }; -ChangeStatus AANoUnwindFunction::updateImpl(Attributor &A, - InformationCache &InfoCache) { +struct AANoUnwindFunction final : public AANoUnwindImpl { + AANoUnwindFunction(Function &F) : AANoUnwindImpl(F, IRP_FUNCTION) {} +}; + +ChangeStatus AANoUnwindImpl::updateImpl(Attributor &A, + InformationCache &InfoCache) { Function &F = getAnchorScope(); // The map from instruction opcodes to those instructions in the function. @@ -507,7 +464,9 @@ /// /// 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 final : public AAReturnedValues, AbstractState { +class AAReturnedValuesImpl : public AAReturnedValues, + public AbstractState, + public IRPosition { /// Mapping of values potentially returned by the associated function to the /// return instructions that might return them. @@ -544,11 +503,8 @@ } public: - /// See AbstractAttribute::AbstractAttribute(...). - AAReturnedValuesImpl(Function &F) : AAReturnedValues(F) { - // We do not have an associated argument yet. - AssociatedVal = nullptr; - } + IRPositionConstructorForward(AAReturnedValuesImpl); + IRPositionGetter(*this); /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -559,7 +515,7 @@ HasOverdefinedReturnedCalls = false; ReturnedValues.clear(); - Function &F = cast(getAnchoredValue()); + Function &F = cast(getAnchorValue()); // The map from instruction opcodes to those instructions in the function. auto &OpcodeInstMap = InfoCache.getOpcodeInstMapForFunction(F); @@ -595,9 +551,6 @@ /// See AbstractAttribute::getState(...). const AbstractState &getState() const override { return *this; } - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_ARGUMENT; } - /// See AbstractAttribute::updateImpl(Attributor &A). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; @@ -640,6 +593,11 @@ } }; +struct AAReturnedValuesFunction final : public AAReturnedValuesImpl { + AAReturnedValuesFunction(Function &F) + : AAReturnedValuesImpl(F, IRP_FUNCTION) {} +}; + ChangeStatus AAReturnedValuesImpl::manifest(Attributor &A) { ChangeStatus Changed = ChangeStatus::UNCHANGED; @@ -660,7 +618,8 @@ // If the assumed unique return value is an argument, annotate it. if (auto *UniqueRVArg = dyn_cast(UniqueRV.getValue())) { - AssociatedVal = UniqueRVArg; + setAssociatedValue(UniqueRVArg); + setAttributeIdx(UniqueRVArg->getArgNo() + AttributeList::FirstArgIndex); Changed = AbstractAttribute::manifest(A) | Changed; } @@ -861,9 +820,9 @@ /// ------------------------ NoSync Function Attribute ------------------------- -struct AANoSyncFunction : AANoSync, BooleanState { - - AANoSyncFunction(Function &F) : AANoSync(F) {} +struct AANoSyncImpl : AANoSync, BooleanState, IRPosition { + IRPositionConstructorForward(AANoSyncImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -871,9 +830,6 @@ const AbstractState &getState() const override { return *this; } /// } - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } - const std::string getAsStr() const override { return getAssumed() ? "nosync" : "may-sync"; } @@ -900,7 +856,11 @@ static bool isNoSyncIntrinsic(Instruction *I); }; -bool AANoSyncFunction::isNonRelaxedAtomic(Instruction *I) { +struct AANoSyncFunction final : public AANoSyncImpl { + AANoSyncFunction(Function &F) : AANoSyncImpl(F, IRP_FUNCTION) {} +}; + +bool AANoSyncImpl::isNonRelaxedAtomic(Instruction *I) { if (!I->isAtomic()) return false; @@ -949,7 +909,7 @@ /// Checks if an intrinsic is nosync. Currently only checks mem* intrinsics. /// FIXME: We should ipmrove the handling of intrinsics. -bool AANoSyncFunction::isNoSyncIntrinsic(Instruction *I) { +bool AANoSyncImpl::isNoSyncIntrinsic(Instruction *I) { if (auto *II = dyn_cast(I)) { switch (II->getIntrinsicID()) { /// Element wise atomic memory intrinsics are can only be unordered, @@ -971,7 +931,7 @@ return false; } -bool AANoSyncFunction::isVolatile(Instruction *I) { +bool AANoSyncImpl::isVolatile(Instruction *I) { assert(!ImmutableCallSite(I) && !isa(I) && "Calls should not be checked here"); @@ -989,8 +949,8 @@ } } -ChangeStatus AANoSyncFunction::updateImpl(Attributor &A, - InformationCache &InfoCache) { +ChangeStatus AANoSyncImpl::updateImpl(Attributor &A, + InformationCache &InfoCache) { Function &F = getAnchorScope(); auto *LivenessAA = A.getAAFor(*this, F); @@ -1003,7 +963,7 @@ continue; ImmutableCallSite ICS(I); - auto *NoSyncAA = A.getAAFor(*this, *I); + auto *NoSyncAA = A.getAAFor(*this, *I); if (isa(I) && isNoSyncIntrinsic(I)) continue; @@ -1050,10 +1010,9 @@ /// ------------------------ No-Free Attributes ---------------------------- -struct AANoFreeFunction : AbstractAttribute, BooleanState { - - /// See AbstractAttribute::AbstractAttribute(...). - AANoFreeFunction(Function &F) : AbstractAttribute(F) {} +struct AANoFreeImpl : AbstractAttribute, BooleanState, IRPosition { + IRPositionConstructorForward(AANoFreeImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() ///{ @@ -1061,9 +1020,6 @@ const AbstractState &getState() const override { return *this; } ///} - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } - /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return getAssumed() ? "nofree" : "may-free"; @@ -1085,8 +1041,12 @@ static const char ID; }; -ChangeStatus AANoFreeFunction::updateImpl(Attributor &A, - InformationCache &InfoCache) { +struct AANoFreeFunction final : public AANoFreeImpl { + AANoFreeFunction(Function &F) : AANoFreeImpl(F, IRP_FUNCTION) {} +}; + +ChangeStatus AANoFreeImpl::updateImpl(Attributor &A, + InformationCache &InfoCache) { Function &F = getAnchorScope(); auto *LivenessAA = A.getAAFor(*this, F); @@ -1102,7 +1062,7 @@ if (LivenessAA && LivenessAA->isAssumedDead(I)) continue; auto ICS = ImmutableCallSite(I); - auto *NoFreeAA = A.getAAFor(*this, *I); + auto *NoFreeAA = A.getAAFor(*this, *I); if ((!NoFreeAA || !NoFreeAA->isAssumedNoFree()) && !ICS.hasFnAttr(Attribute::NoFree)) @@ -1113,12 +1073,9 @@ } /// ------------------------ NonNull Argument Attribute ------------------------ -struct AANonNullImpl : AANonNull, BooleanState { - - AANonNullImpl(Value &V) : AANonNull(V) {} - - AANonNullImpl(Value *AssociatedVal, Value &AnchoredValue) - : AANonNull(AssociatedVal, AnchoredValue) {} +struct AANonNullImpl : AANonNull, BooleanState, IRPosition { + IRPositionConstructorForward(AANonNullImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -1178,10 +1135,7 @@ /// NonNull attribute for function return value. struct AANonNullReturned : AANonNullImpl { - AANonNullReturned(Function &F) : AANonNullImpl(F) {} - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_RETURNED; } + AANonNullReturned(Function &F) : AANonNullImpl(F, IRP_RETURNED) {} /// See AbstractAttriubute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -1220,9 +1174,6 @@ AANonNullArgument(Argument &A) : AANonNullImpl(A) {} - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_ARGUMENT; } - /// See AbstractAttriubute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { Argument *Arg = cast(getAssociatedValue()); @@ -1239,14 +1190,13 @@ /// See AANonNullImpl::AANonNullImpl(...). AANonNullCallSiteArgument(CallSite CS, unsigned ArgNo) - : AANonNullImpl(CS.getArgOperand(ArgNo), *CS.getInstruction()), - ArgNo(ArgNo) {} + : AANonNullImpl(CS.getArgOperand(ArgNo), *CS.getInstruction(), ArgNo) {} /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { - CallSite CS(&getAnchoredValue()); - if (CS.paramHasAttr(ArgNo, getAttrKind()) || - CS.paramHasAttr(ArgNo, Attribute::Dereferenceable) || + CallSite CS(&getAnchorValue()); + if (CS.paramHasAttr(getArgNo(), getAttrKind()) || + CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable) || isKnownNonZero(getAssociatedValue(), getAnchorScope().getParent()->getDataLayout())) indicateOptimisticFixpoint(); @@ -1254,23 +1204,12 @@ /// See AbstractAttribute::updateImpl(Attributor &A). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { - return MP_CALL_SITE_ARGUMENT; - }; - - // Return argument index of associated value. - int getArgNo() const { return ArgNo; } - -private: - unsigned ArgNo; }; ChangeStatus AANonNullArgument::updateImpl(Attributor &A, InformationCache &InfoCache) { Function &F = getAnchorScope(); - Argument &Arg = cast(getAnchoredValue()); + Argument &Arg = cast(getAnchorValue()); unsigned ArgNo = Arg.getArgNo(); @@ -1282,7 +1221,7 @@ // Check that NonNullAA is AANonNullCallSiteArgument. if (NonNullAA) { - ImmutableCallSite ICS(&NonNullAA->getAnchoredValue()); + ImmutableCallSite ICS(&NonNullAA->getIRPosition().getAnchorValue()); if (ICS && CS.getInstruction() == ICS.getInstruction()) return NonNullAA->isAssumedNonNull(); return false; @@ -1320,10 +1259,9 @@ /// ------------------------ Will-Return Attributes ---------------------------- -struct AAWillReturnImpl : public AAWillReturn, BooleanState { - - /// See AbstractAttribute::AbstractAttribute(...). - AAWillReturnImpl(Function &F) : AAWillReturn(F) {} +struct AAWillReturnImpl : public AAWillReturn, BooleanState, IRPosition { + IRPositionConstructorForward(AAWillReturnImpl); + IRPositionGetter(*this); /// See AAWillReturn::isKnownWillReturn(). bool isKnownWillReturn() const override { return getKnown(); } @@ -1346,10 +1284,7 @@ struct AAWillReturnFunction final : AAWillReturnImpl { /// See AbstractAttribute::AbstractAttribute(...). - AAWillReturnFunction(Function &F) : AAWillReturnImpl(F) {} - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } + AAWillReturnFunction(Function &F) : AAWillReturnImpl(F, IRP_FUNCTION) {} /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override; @@ -1431,9 +1366,9 @@ /// ------------------------ NoAlias Argument Attribute ------------------------ -struct AANoAliasImpl : AANoAlias, BooleanState { - - AANoAliasImpl(Value &V) : AANoAlias(V) {} +struct AANoAliasImpl : AANoAlias, BooleanState, IRPosition { + IRPositionConstructorForward(AANoAliasImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -1455,12 +1390,7 @@ /// NoAlias attribute for function return value. struct AANoAliasReturned : AANoAliasImpl { - AANoAliasReturned(Function &F) : AANoAliasImpl(F) {} - - /// See AbstractAttribute::getManifestPosition(). - virtual ManifestPosition getManifestPosition() const override { - return MP_RETURNED; - } + AANoAliasReturned(Function &F) : AANoAliasImpl(F, IRP_RETURNED) {} /// See AbstractAttriubute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { @@ -1522,18 +1452,9 @@ /// -------------------AAIsDead Function Attribute----------------------- -struct AAIsDeadFunction : AAIsDead, BooleanState { - - AAIsDeadFunction(Function &F) : AAIsDead(F) {} - - /// See AbstractAttribute::getState() - /// { - AbstractState &getState() override { return *this; } - const AbstractState &getState() const override { return *this; } - /// } - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } +struct AAIsDeadImpl : public AAIsDead, BooleanState, IRPosition { + IRPositionConstructorForward(AAIsDeadImpl); + IRPositionGetter(*this); void initialize(Attributor &A, InformationCache &InfoCache) override { Function &F = getAnchorScope(); @@ -1643,6 +1564,12 @@ /// Check if instruction is after noreturn call, in other words, assumed dead. bool isAfterNoReturn(const Instruction *I) const; + /// See AbstractAttribute::getState() + /// { + AbstractState &getState() override { return *this; } + const AbstractState &getState() const override { return *this; } + /// } + /// Collection of to be explored paths. SmallSetVector ToBeExploredPaths; @@ -1653,7 +1580,11 @@ SmallSetVector NoReturnCalls; }; -bool AAIsDeadFunction::isAfterNoReturn(const Instruction *I) const { +struct AAIsDeadFunction final : public AAIsDeadImpl { + AAIsDeadFunction(Function &F) : AAIsDeadImpl(F, IRP_FUNCTION) {} +}; + +bool AAIsDeadImpl::isAfterNoReturn(const Instruction *I) const { const Instruction *PrevI = I->getPrevNode(); while (PrevI) { if (NoReturnCalls.count(PrevI)) @@ -1663,8 +1594,8 @@ return false; } -const Instruction *AAIsDeadFunction::findNextNoReturn(Attributor &A, - const Instruction *I) { +const Instruction *AAIsDeadImpl::findNextNoReturn(Attributor &A, + const Instruction *I) { const BasicBlock *BB = I->getParent(); // TODO: We should have a function that determines if an "edge" is dead. @@ -1707,8 +1638,8 @@ return nullptr; } -ChangeStatus AAIsDeadFunction::updateImpl(Attributor &A, - InformationCache &InfoCache) { +ChangeStatus AAIsDeadImpl::updateImpl(Attributor &A, + InformationCache &InfoCache) { // Temporary collection to iterate over existing noreturn instructions. This // will alow easier modification of NoReturnCalls collection SmallVector NoReturnChanged; @@ -1807,12 +1738,10 @@ this->NonNullGlobalState == R.NonNullGlobalState; } }; -struct AADereferenceableImpl : AADereferenceable, DerefState { - - AADereferenceableImpl(Value &V) : AADereferenceable(V) {} - AADereferenceableImpl(Value *AssociatedVal, Value &AnchoredValue) - : AADereferenceable(AssociatedVal, AnchoredValue) {} +struct AADereferenceableImpl : AADereferenceable, DerefState, IRPosition { + IRPositionConstructorForward(AADereferenceableImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -1865,7 +1794,7 @@ } void getDeducedAttributes(SmallVectorImpl &Attrs) const override { - LLVMContext &Ctx = AnchoredVal.getContext(); + LLVMContext &Ctx = AnchorVal.getContext(); // TODO: Add *_globally support if (isAssumedNonNull()) @@ -1880,8 +1809,7 @@ void initialize(Attributor &A, InformationCache &InfoCache) override { Function &F = getAnchorScope(); - unsigned AttrIdx = - getAttrIndex(getManifestPosition(), getArgNo(getAnchoredValue())); + unsigned AttrIdx = getIRPosition().getAttrIdx(); for (Attribute::AttrKind AK : {Attribute::Dereferenceable, Attribute::DereferenceableOrNull}) @@ -1902,10 +1830,8 @@ }; struct AADereferenceableReturned : AADereferenceableImpl { - AADereferenceableReturned(Function &F) : AADereferenceableImpl(F) {} - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_RETURNED; } + AADereferenceableReturned(Function &F) + : AADereferenceableImpl(F, IRP_RETURNED) {} /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; @@ -1991,9 +1917,6 @@ struct AADereferenceableArgument : AADereferenceableImpl { AADereferenceableArgument(Argument &A) : AADereferenceableImpl(A) {} - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_ARGUMENT; } - /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; }; @@ -2002,7 +1925,7 @@ AADereferenceableArgument::updateImpl(Attributor &A, InformationCache &InfoCache) { Function &F = getAnchorScope(); - Argument &Arg = cast(getAnchoredValue()); + Argument &Arg = cast(getAnchorValue()); auto BeforeState = static_cast(*this); @@ -2020,7 +1943,8 @@ // Check that DereferenceableAA is AADereferenceableCallSiteArgument. if (auto *DereferenceableAA = A.getAAFor(*this, *CS.getInstruction(), ArgNo)) { - ImmutableCallSite ICS(&DereferenceableAA->getAnchoredValue()); + ImmutableCallSite ICS( + &DereferenceableAA->getIRPosition().getAnchorValue()); if (ICS && CS.getInstruction() == ICS.getInstruction()) { takeAssumedDerefBytesMinimum( DereferenceableAA->getAssumedDereferenceableBytes()); @@ -2050,32 +1974,21 @@ /// See AADereferenceableImpl::AADereferenceableImpl(...). AADereferenceableCallSiteArgument(CallSite CS, unsigned ArgNo) - : AADereferenceableImpl(CS.getArgOperand(ArgNo), *CS.getInstruction()), - ArgNo(ArgNo) {} + : AADereferenceableImpl(CS.getArgOperand(ArgNo), *CS.getInstruction(), + ArgNo) {} /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { - CallSite CS(&getAnchoredValue()); - if (CS.paramHasAttr(ArgNo, Attribute::Dereferenceable)) - takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(ArgNo)); + CallSite CS(&getAnchorValue()); + if (CS.paramHasAttr(getArgNo(), Attribute::Dereferenceable)) + takeKnownDerefBytesMaximum(CS.getDereferenceableBytes(getArgNo())); - if (CS.paramHasAttr(ArgNo, Attribute::DereferenceableOrNull)) - takeKnownDerefBytesMaximum(CS.getDereferenceableOrNullBytes(ArgNo)); + if (CS.paramHasAttr(getArgNo(), Attribute::DereferenceableOrNull)) + takeKnownDerefBytesMaximum(CS.getDereferenceableOrNullBytes(getArgNo())); } /// See AbstractAttribute::updateImpl(Attributor &A). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { - return MP_CALL_SITE_ARGUMENT; - }; - - // Return argument index of associated value. - int getArgNo() const { return ArgNo; } - -private: - unsigned ArgNo; }; ChangeStatus @@ -2089,7 +2002,7 @@ auto BeforeState = static_cast(*this); - syncNonNull(A.getAAFor(*this, getAnchoredValue(), ArgNo)); + syncNonNull(A.getAAFor(*this, getAnchorValue(), getArgNo())); bool IsNonNull = isAssumedNonNull(); bool IsGlobal = isKnownGlobal(); @@ -2103,16 +2016,13 @@ // ------------------------ Align Argument Attribute ------------------------ -struct AAAlignImpl : AAAlign, IntegerState { +struct AAAlignImpl : AAAlign, IntegerState, IRPosition { + IRPositionConstructorForward(AAAlignImpl); + IRPositionGetter(*this); // Max alignemnt value allowed in IR static const unsigned MAX_ALIGN = 1U << 29; - AAAlignImpl(Value *AssociatedVal, Value &AnchoredValue) - : AAAlign(AssociatedVal, AnchoredValue), IntegerState(MAX_ALIGN) {} - - AAAlignImpl(Value &V) : AAAlignImpl(&V, V) {} - /// See AbstractAttribute::getState() /// { AbstractState &getState() override { return *this; } @@ -2133,10 +2043,11 @@ /// See AbstractAttriubute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { + takeAssumedMinimum(MAX_ALIGN); + Function &F = getAnchorScope(); - unsigned AttrIdx = - getAttrIndex(getManifestPosition(), getArgNo(getAnchoredValue())); + unsigned AttrIdx = getIRPosition().getAttrIdx(); // Already the function has align attribute on return value or argument. if (F.getAttributes().hasAttribute(AttrIdx, Attribute::Alignment)) @@ -2147,21 +2058,16 @@ /// See AbstractAttribute::getDeducedAttributes virtual void getDeducedAttributes(SmallVectorImpl &Attrs) const override { - LLVMContext &Ctx = AnchoredVal.getContext(); + LLVMContext &Ctx = AnchorVal.getContext(); Attrs.emplace_back(Attribute::getWithAlignment(Ctx, getAssumedAlign())); } }; /// Align attribute for function return value. -struct AAAlignReturned : AAAlignImpl { +struct AAAlignReturned final : AAAlignImpl { - AAAlignReturned(Function &F) : AAAlignImpl(F) {} - - /// See AbstractAttribute::getManifestPosition(). - virtual ManifestPosition getManifestPosition() const override { - return MP_RETURNED; - } + AAAlignReturned(Function &F) : AAAlignImpl(F, IRP_RETURNED) {} /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; @@ -2202,15 +2108,10 @@ } /// Align attribute for function argument. -struct AAAlignArgument : AAAlignImpl { +struct AAAlignArgument final : AAAlignImpl { AAAlignArgument(Argument &A) : AAAlignImpl(A) {} - /// See AbstractAttribute::getManifestPosition(). - virtual ManifestPosition getManifestPosition() const override { - return MP_ARGUMENT; - } - /// See AbstractAttribute::updateImpl(...). virtual ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; @@ -2220,7 +2121,7 @@ InformationCache &InfoCache) { Function &F = getAnchorScope(); - Argument &Arg = cast(getAnchoredValue()); + Argument &Arg = cast(getAnchorValue()); unsigned ArgNo = Arg.getArgNo(); const DataLayout &DL = F.getParent()->getDataLayout(); @@ -2235,7 +2136,7 @@ // Check that AlignAA is AAAlignCallSiteArgument. if (AlignAA) { - ImmutableCallSite ICS(&AlignAA->getAnchoredValue()); + ImmutableCallSite ICS(&AlignAA->getIRPosition().getAnchorValue()); if (ICS && CS.getInstruction() == ICS.getInstruction()) { takeAssumedMinimum(AlignAA->getAssumedAlign()); return isValidState(); @@ -2254,33 +2155,21 @@ : ChangeStatus ::CHANGED; } -struct AAAlignCallSiteArgument : AAAlignImpl { +struct AAAlignCallSiteArgument final : AAAlignImpl { /// See AANonNullImpl::AANonNullImpl(...). AAAlignCallSiteArgument(CallSite CS, unsigned ArgNo) - : AAAlignImpl(CS.getArgOperand(ArgNo), *CS.getInstruction()), - ArgNo(ArgNo) {} + : AAAlignImpl(CS.getArgOperand(ArgNo), *CS.getInstruction(), ArgNo) {} /// See AbstractAttribute::initialize(...). void initialize(Attributor &A, InformationCache &InfoCache) override { - CallSite CS(&getAnchoredValue()); + CallSite CS(&getAnchorValue()); takeKnownMaximum(getAssociatedValue()->getPointerAlignment( getAnchorScope().getParent()->getDataLayout())); } /// See AbstractAttribute::updateImpl(Attributor &A). ChangeStatus updateImpl(Attributor &A, InformationCache &InfoCache) override; - - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { - return MP_CALL_SITE_ARGUMENT; - }; - - // Return argument index of associated value. - int getArgNo() const { return ArgNo; } - -private: - unsigned ArgNo; }; ChangeStatus AAAlignCallSiteArgument::updateImpl(Attributor &A, @@ -2304,9 +2193,9 @@ } /// ------------------ Function No-Return Attribute ---------------------------- -struct AANoReturnFunction final : public AANoReturn, BooleanState { - - AANoReturnFunction(Function &F) : AANoReturn(F) {} +struct AANoReturnImpl : public AANoReturn, BooleanState, IRPosition { + IRPositionConstructorForward(AANoReturnImpl); + IRPositionGetter(*this); /// See AbstractAttribute::getState() /// { @@ -2320,9 +2209,6 @@ /// Return true if the underlying object is assumed to never return. bool isAssumedNoReturn() const override { return getAssumed(); } - /// See AbstractAttribute::getManifestPosition(). - ManifestPosition getManifestPosition() const override { return MP_FUNCTION; } - /// See AbstractAttribute::getAsStr(). const std::string getAsStr() const override { return getAssumed() ? "noreturn" : "may-return"; @@ -2357,6 +2243,10 @@ } }; +struct AANoReturnFunction final : AANoReturnImpl { + AANoReturnFunction(Function &F) : AANoReturnImpl(F, IRP_FUNCTION) {} +}; + /// ---------------------------------------------------------------------------- /// Attributor /// ---------------------------------------------------------------------------- @@ -2569,7 +2459,7 @@ // Argument attribute "returned" --- Create only one per function even // though it is an argument attribute. if (!Whitelist || Whitelist->count(&AAReturnedValues::ID)) - registerAA(*new AAReturnedValuesImpl(F)); + registerAA(*new AAReturnedValuesFunction(F)); if (ReturnType->isPointerTy()) { // Every function with pointer return type might be marked align. @@ -2672,21 +2562,27 @@ return OS << (S == ChangeStatus::CHANGED ? "changed" : "unchanged"); } -raw_ostream &llvm::operator<<(raw_ostream &OS, - AbstractAttribute::ManifestPosition AP) { +raw_ostream &llvm::operator<<(raw_ostream &OS, IRPosition::Kind AP) { switch (AP) { - case AbstractAttribute::MP_ARGUMENT: + case IRPosition::IRP_ARGUMENT: return OS << "arg"; - case AbstractAttribute::MP_CALL_SITE_ARGUMENT: + case IRPosition::IRP_CALL_SITE_ARGUMENT: return OS << "cs_arg"; - case AbstractAttribute::MP_FUNCTION: + case IRPosition::IRP_FUNCTION: return OS << "fn"; - case AbstractAttribute::MP_RETURNED: + case IRPosition::IRP_RETURNED: return OS << "fn_ret"; } llvm_unreachable("Unknown attribute position!"); } +raw_ostream &llvm::operator<<(raw_ostream &OS, const IRPosition &Pos) { + const Value *AV = Pos.getAssociatedValue(); + return OS << "{" << Pos.getPositionKind() << ":" + << (AV ? AV->getName() : "n/a") << " [" + << Pos.getAnchorValue().getName() << "@" << Pos.getArgNo() << "]}"; +} + raw_ostream &llvm::operator<<(raw_ostream &OS, const AbstractState &S) { return OS << (!S.isValidState() ? "top" : (S.isAtFixpoint() ? "fix" : "")); } @@ -2697,8 +2593,8 @@ } void AbstractAttribute::print(raw_ostream &OS) const { - OS << "[" << getManifestPosition() << "][" << getAsStr() << "][" - << AnchoredVal.getName() << "]"; + OS << "[P: " << getIRPosition() << "][" << getAsStr() << "][S: " << getState() + << "]"; } ///} @@ -2784,7 +2680,7 @@ const char AAReturnedValues::ID = 0; const char AANoUnwind::ID = 0; const char AANoSync::ID = 0; -const char AANoFreeFunction::ID = 0; +const char AANoFreeImpl::ID = 0; const char AANonNull::ID = 0; const char AANoRecurse::ID = 0; const char AAWillReturn::ID = 0;