forked from OSchip/llvm-project
[Attributor][NFC] Let AbstractAttribute be an IRPosition
Since every AbstractAttribute so far, and for the foreseeable future, corresponds to a single IRPosition we can simplify the class structure. We already did this for IRAttribute but there is no reason to stop there.
This commit is contained in:
parent
fb5fd74685
commit
6bf16ee4c5
|
@ -1754,11 +1754,14 @@ struct IRAttributeManifest {
|
|||
};
|
||||
|
||||
/// Helper to tie a abstract state implementation to an abstract attribute.
|
||||
template <typename StateTy, typename Base>
|
||||
struct StateWrapper : public StateTy, public Base {
|
||||
template <typename StateTy, typename BaseType, class... Ts>
|
||||
struct StateWrapper : public BaseType, public StateTy {
|
||||
/// Provide static access to the type of the state.
|
||||
using StateType = StateTy;
|
||||
|
||||
StateWrapper(const IRPosition &IRP, Ts... Args)
|
||||
: BaseType(IRP), StateTy(Args...) {}
|
||||
|
||||
/// See AbstractAttribute::getState(...).
|
||||
StateType &getState() override { return *this; }
|
||||
|
||||
|
@ -1767,16 +1770,16 @@ struct StateWrapper : public StateTy, public Base {
|
|||
};
|
||||
|
||||
/// Helper class that provides common functionality to manifest IR attributes.
|
||||
template <Attribute::AttrKind AK, typename Base>
|
||||
struct IRAttribute : public IRPosition, public Base {
|
||||
IRAttribute(const IRPosition &IRP) : IRPosition(IRP) {}
|
||||
~IRAttribute() {}
|
||||
template <Attribute::AttrKind AK, typename BaseType>
|
||||
struct IRAttribute : public BaseType {
|
||||
IRAttribute(const IRPosition &IRP) : BaseType(IRP) {}
|
||||
|
||||
/// See AbstractAttribute::initialize(...).
|
||||
virtual void initialize(Attributor &A) override {
|
||||
const IRPosition &IRP = this->getIRPosition();
|
||||
if (isa<UndefValue>(IRP.getAssociatedValue()) ||
|
||||
hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ false, &A)) {
|
||||
this->hasAttr(getAttrKind(), /* IgnoreSubsumingPositions */ false,
|
||||
&A)) {
|
||||
this->getState().indicateOptimisticFixpoint();
|
||||
return;
|
||||
}
|
||||
|
@ -1796,11 +1799,12 @@ struct IRAttribute : public IRPosition, public Base {
|
|||
|
||||
/// See AbstractAttribute::manifest(...).
|
||||
ChangeStatus manifest(Attributor &A) override {
|
||||
if (isa<UndefValue>(getIRPosition().getAssociatedValue()))
|
||||
if (isa<UndefValue>(this->getIRPosition().getAssociatedValue()))
|
||||
return ChangeStatus::UNCHANGED;
|
||||
SmallVector<Attribute, 4> DeducedAttrs;
|
||||
getDeducedAttributes(getAnchorValue().getContext(), DeducedAttrs);
|
||||
return IRAttributeManifest::manifestAttrs(A, getIRPosition(), DeducedAttrs);
|
||||
getDeducedAttributes(this->getAnchorValue().getContext(), DeducedAttrs);
|
||||
return IRAttributeManifest::manifestAttrs(A, this->getIRPosition(),
|
||||
DeducedAttrs);
|
||||
}
|
||||
|
||||
/// Return the kind that identifies the abstract attribute implementation.
|
||||
|
@ -1811,9 +1815,6 @@ struct IRAttribute : public IRPosition, public Base {
|
|||
SmallVectorImpl<Attribute> &Attrs) const {
|
||||
Attrs.emplace_back(Attribute::get(Ctx, getAttrKind()));
|
||||
}
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const override { return *this; }
|
||||
};
|
||||
|
||||
/// Base struct for all "concrete attribute" deductions.
|
||||
|
@ -1859,9 +1860,11 @@ struct IRAttribute : public IRPosition, public Base {
|
|||
/// both directions will be added in the future.
|
||||
/// NOTE: The mechanics of adding a new "concrete" abstract attribute are
|
||||
/// described in the file comment.
|
||||
struct AbstractAttribute {
|
||||
struct AbstractAttribute : public IRPosition {
|
||||
using StateType = AbstractState;
|
||||
|
||||
AbstractAttribute(const IRPosition &IRP) : IRPosition(IRP) {}
|
||||
|
||||
/// Virtual destructor.
|
||||
virtual ~AbstractAttribute() {}
|
||||
|
||||
|
@ -1880,7 +1883,8 @@ struct AbstractAttribute {
|
|||
virtual const StateType &getState() const = 0;
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
virtual const IRPosition &getIRPosition() const = 0;
|
||||
const IRPosition &getIRPosition() const { return *this; };
|
||||
IRPosition &getIRPosition() { return *this; };
|
||||
|
||||
/// Helper functions, for debug purposes only.
|
||||
///{
|
||||
|
@ -2096,9 +2100,9 @@ struct AAWillReturn
|
|||
|
||||
/// An abstract attribute for undefined behavior.
|
||||
struct AAUndefinedBehavior
|
||||
: public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAUndefinedBehavior(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
: public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAUndefinedBehavior(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
/// Return true if "undefined behavior" is assumed.
|
||||
bool isAssumedToCauseUB() const { return getAssumed(); }
|
||||
|
@ -2112,9 +2116,6 @@ struct AAUndefinedBehavior
|
|||
/// Return true if "undefined behavior" is known for a specific instruction.
|
||||
virtual bool isKnownToCauseUB(Instruction *I) const = 0;
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const override { return *this; }
|
||||
|
||||
/// Create an abstract attribute view for the position \p IRP.
|
||||
static AAUndefinedBehavior &createForPosition(const IRPosition &IRP,
|
||||
Attributor &A);
|
||||
|
@ -2124,9 +2125,9 @@ struct AAUndefinedBehavior
|
|||
};
|
||||
|
||||
/// An abstract interface to determine reachability of point A to B.
|
||||
struct AAReachability : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAReachability(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
struct AAReachability : public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAReachability(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
/// Returns true if 'From' instruction is assumed to reach, 'To' instruction.
|
||||
/// Users should provide two positions they are interested in, and the class
|
||||
|
@ -2143,9 +2144,6 @@ struct AAReachability : public StateWrapper<BooleanState, AbstractAttribute>,
|
|||
return isPotentiallyReachable(From, To);
|
||||
}
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const override { return *this; }
|
||||
|
||||
/// Create an abstract attribute view for the position \p IRP.
|
||||
static AAReachability &createForPosition(const IRPosition &IRP,
|
||||
Attributor &A);
|
||||
|
@ -2212,9 +2210,9 @@ struct AANoReturn
|
|||
};
|
||||
|
||||
/// An abstract interface for liveness abstract attribute.
|
||||
struct AAIsDead : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAIsDead(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
struct AAIsDead : public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAIsDead(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
protected:
|
||||
/// The query functions are protected such that other attributes need to go
|
||||
|
@ -2253,9 +2251,6 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const override { return *this; }
|
||||
|
||||
/// Create an abstract attribute view for the position \p IRP.
|
||||
static AAIsDead &createForPosition(const IRPosition &IRP, Attributor &A);
|
||||
|
||||
|
@ -2531,12 +2526,9 @@ struct AANoCapture
|
|||
};
|
||||
|
||||
/// An abstract interface for value simplify abstract attribute.
|
||||
struct AAValueSimplify : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAValueSimplify(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const { return *this; }
|
||||
struct AAValueSimplify : public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAValueSimplify(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
/// Return an assumed simplified value if a single candidate is found. If
|
||||
/// there cannot be one, return original value. If it is not clear yet, return
|
||||
|
@ -2551,9 +2543,9 @@ struct AAValueSimplify : public StateWrapper<BooleanState, AbstractAttribute>,
|
|||
static const char ID;
|
||||
};
|
||||
|
||||
struct AAHeapToStack : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAHeapToStack(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
struct AAHeapToStack : public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAHeapToStack(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
/// Returns true if HeapToStack conversion is assumed to be possible.
|
||||
bool isAssumedHeapToStack() const { return getAssumed(); }
|
||||
|
@ -2561,9 +2553,6 @@ struct AAHeapToStack : public StateWrapper<BooleanState, AbstractAttribute>,
|
|||
/// Returns true if HeapToStack conversion is known to be possible.
|
||||
bool isKnownHeapToStack() const { return getKnown(); }
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const { return *this; }
|
||||
|
||||
/// Create an abstract attribute view for the position \p IRP.
|
||||
static AAHeapToStack &createForPosition(const IRPosition &IRP, Attributor &A);
|
||||
|
||||
|
@ -2581,9 +2570,10 @@ struct AAHeapToStack : public StateWrapper<BooleanState, AbstractAttribute>,
|
|||
/// (=nocapture), it is (for now) not written (=readonly & noalias), we know
|
||||
/// what values are necessary to make the private copy look like the original
|
||||
/// one, and the values we need can be loaded (=dereferenceable).
|
||||
struct AAPrivatizablePtr : public StateWrapper<BooleanState, AbstractAttribute>,
|
||||
public IRPosition {
|
||||
AAPrivatizablePtr(const IRPosition &IRP, Attributor &A) : IRPosition(IRP) {}
|
||||
struct AAPrivatizablePtr
|
||||
: public StateWrapper<BooleanState, AbstractAttribute> {
|
||||
using Base = StateWrapper<BooleanState, AbstractAttribute>;
|
||||
AAPrivatizablePtr(const IRPosition &IRP, Attributor &A) : Base(IRP) {}
|
||||
|
||||
/// Returns true if pointer privatization is assumed to be possible.
|
||||
bool isAssumedPrivatizablePtr() const { return getAssumed(); }
|
||||
|
@ -2595,13 +2585,6 @@ struct AAPrivatizablePtr : public StateWrapper<BooleanState, AbstractAttribute>,
|
|||
/// value. None means it is not clear yet, nullptr means there is none.
|
||||
virtual Optional<Type *> getPrivatizableType() const = 0;
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
///
|
||||
///{
|
||||
IRPosition &getIRPosition() { return *this; }
|
||||
const IRPosition &getIRPosition() const { return *this; }
|
||||
///}
|
||||
|
||||
/// Create an abstract attribute view for the position \p IRP.
|
||||
static AAPrivatizablePtr &createForPosition(const IRPosition &IRP,
|
||||
Attributor &A);
|
||||
|
@ -2820,15 +2803,11 @@ struct AAMemoryLocation
|
|||
};
|
||||
|
||||
/// An abstract interface for range value analysis.
|
||||
struct AAValueConstantRange : public IntegerRangeState,
|
||||
public AbstractAttribute,
|
||||
public IRPosition {
|
||||
struct AAValueConstantRange
|
||||
: public StateWrapper<IntegerRangeState, AbstractAttribute, uint32_t> {
|
||||
using Base = StateWrapper<IntegerRangeState, AbstractAttribute, uint32_t>;
|
||||
AAValueConstantRange(const IRPosition &IRP, Attributor &A)
|
||||
: IntegerRangeState(IRP.getAssociatedType()->getIntegerBitWidth()),
|
||||
IRPosition(IRP) {}
|
||||
|
||||
/// Return an IR position, see struct IRPosition.
|
||||
const IRPosition &getIRPosition() const override { return *this; }
|
||||
: Base(IRP, IRP.getAssociatedType()->getIntegerBitWidth()) {}
|
||||
|
||||
/// See AbstractAttribute::getState(...).
|
||||
IntegerRangeState &getState() override { return *this; }
|
||||
|
|
|
@ -401,33 +401,33 @@ static void clampReturnedValueStates(Attributor &A, const AAType &QueryingAA,
|
|||
}
|
||||
|
||||
/// Helper class to compose two generic deduction
|
||||
template <typename AAType, typename Base, typename StateType,
|
||||
template <typename AAType, typename BaseType, typename StateType,
|
||||
template <typename...> class F, template <typename...> class G>
|
||||
struct AAComposeTwoGenericDeduction
|
||||
: public F<AAType, G<AAType, Base, StateType>, StateType> {
|
||||
: public F<AAType, G<AAType, BaseType, StateType>, StateType> {
|
||||
AAComposeTwoGenericDeduction(const IRPosition &IRP, Attributor &A)
|
||||
: F<AAType, G<AAType, Base, StateType>, StateType>(IRP, A) {}
|
||||
: F<AAType, G<AAType, BaseType, StateType>, StateType>(IRP, A) {}
|
||||
|
||||
void initialize(Attributor &A) override {
|
||||
F<AAType, G<AAType, Base, StateType>, StateType>::initialize(A);
|
||||
G<AAType, Base, StateType>::initialize(A);
|
||||
F<AAType, G<AAType, BaseType, StateType>, StateType>::initialize(A);
|
||||
G<AAType, BaseType, StateType>::initialize(A);
|
||||
}
|
||||
|
||||
/// See AbstractAttribute::updateImpl(...).
|
||||
ChangeStatus updateImpl(Attributor &A) override {
|
||||
ChangeStatus ChangedF =
|
||||
F<AAType, G<AAType, Base, StateType>, StateType>::updateImpl(A);
|
||||
ChangeStatus ChangedG = G<AAType, Base, StateType>::updateImpl(A);
|
||||
F<AAType, G<AAType, BaseType, StateType>, StateType>::updateImpl(A);
|
||||
ChangeStatus ChangedG = G<AAType, BaseType, StateType>::updateImpl(A);
|
||||
return ChangedF | ChangedG;
|
||||
}
|
||||
};
|
||||
|
||||
/// Helper class for generic deduction: return value -> returned position.
|
||||
template <typename AAType, typename Base,
|
||||
typename StateType = typename Base::StateType>
|
||||
struct AAReturnedFromReturnedValues : public Base {
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename BaseType::StateType>
|
||||
struct AAReturnedFromReturnedValues : public BaseType {
|
||||
AAReturnedFromReturnedValues(const IRPosition &IRP, Attributor &A)
|
||||
: Base(IRP, A) {}
|
||||
: BaseType(IRP, A) {}
|
||||
|
||||
/// See AbstractAttribute::updateImpl(...).
|
||||
ChangeStatus updateImpl(Attributor &A) override {
|
||||
|
@ -487,11 +487,11 @@ static void clampCallSiteArgumentStates(Attributor &A, const AAType &QueryingAA,
|
|||
}
|
||||
|
||||
/// Helper class for generic deduction: call site argument -> argument position.
|
||||
template <typename AAType, typename Base,
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename AAType::StateType>
|
||||
struct AAArgumentFromCallSiteArguments : public Base {
|
||||
struct AAArgumentFromCallSiteArguments : public BaseType {
|
||||
AAArgumentFromCallSiteArguments(const IRPosition &IRP, Attributor &A)
|
||||
: Base(IRP, A) {}
|
||||
: BaseType(IRP, A) {}
|
||||
|
||||
/// See AbstractAttribute::updateImpl(...).
|
||||
ChangeStatus updateImpl(Attributor &A) override {
|
||||
|
@ -504,11 +504,11 @@ struct AAArgumentFromCallSiteArguments : public Base {
|
|||
};
|
||||
|
||||
/// Helper class for generic replication: function returned -> cs returned.
|
||||
template <typename AAType, typename Base,
|
||||
typename StateType = typename Base::StateType>
|
||||
struct AACallSiteReturnedFromReturned : public Base {
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename BaseType::StateType>
|
||||
struct AACallSiteReturnedFromReturned : public BaseType {
|
||||
AACallSiteReturnedFromReturned(const IRPosition &IRP, Attributor &A)
|
||||
: Base(IRP, A) {}
|
||||
: BaseType(IRP, A) {}
|
||||
|
||||
/// See AbstractAttribute::updateImpl(...).
|
||||
ChangeStatus updateImpl(Attributor &A) override {
|
||||
|
@ -531,21 +531,21 @@ struct AACallSiteReturnedFromReturned : public Base {
|
|||
};
|
||||
|
||||
/// Helper class for generic deduction using must-be-executed-context
|
||||
/// Base class is required to have `followUse` method.
|
||||
/// BaseType class is required to have `followUse` method.
|
||||
|
||||
/// bool followUse(Attributor &A, const Use *U, const Instruction *I)
|
||||
/// U - Underlying use.
|
||||
/// I - The user of the \p U.
|
||||
/// `followUse` returns true if the value should be tracked transitively.
|
||||
|
||||
template <typename AAType, typename Base,
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename AAType::StateType>
|
||||
struct AAFromMustBeExecutedContext : public Base {
|
||||
struct AAFromMustBeExecutedContext : public BaseType {
|
||||
AAFromMustBeExecutedContext(const IRPosition &IRP, Attributor &A)
|
||||
: Base(IRP, A) {}
|
||||
: BaseType(IRP, A) {}
|
||||
|
||||
void initialize(Attributor &A) override {
|
||||
Base::initialize(A);
|
||||
BaseType::initialize(A);
|
||||
const IRPosition &IRP = this->getIRPosition();
|
||||
Instruction *CtxI = IRP.getCtxI();
|
||||
|
||||
|
@ -566,7 +566,7 @@ struct AAFromMustBeExecutedContext : public Base {
|
|||
const Use *U = Uses[u];
|
||||
if (const Instruction *UserI = dyn_cast<Instruction>(U->getUser())) {
|
||||
bool Found = Explorer.findInContextOf(UserI, EIt, EEnd);
|
||||
if (Found && Base::followUse(A, U, UserI, State))
|
||||
if (Found && BaseType::followUse(A, U, UserI, State))
|
||||
for (const Use &Us : UserI->uses())
|
||||
Uses.insert(&Us);
|
||||
}
|
||||
|
@ -662,17 +662,17 @@ private:
|
|||
SetVector<const Use *> Uses;
|
||||
};
|
||||
|
||||
template <typename AAType, typename Base,
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename AAType::StateType>
|
||||
using AAArgumentFromCallSiteArgumentsAndMustBeExecutedContext =
|
||||
AAComposeTwoGenericDeduction<AAType, Base, StateType,
|
||||
AAComposeTwoGenericDeduction<AAType, BaseType, StateType,
|
||||
AAFromMustBeExecutedContext,
|
||||
AAArgumentFromCallSiteArguments>;
|
||||
|
||||
template <typename AAType, typename Base,
|
||||
template <typename AAType, typename BaseType,
|
||||
typename StateType = typename AAType::StateType>
|
||||
using AACallSiteReturnedFromReturnedAndMustBeExecutedContext =
|
||||
AAComposeTwoGenericDeduction<AAType, Base, StateType,
|
||||
AAComposeTwoGenericDeduction<AAType, BaseType, StateType,
|
||||
AAFromMustBeExecutedContext,
|
||||
AACallSiteReturnedFromReturned>;
|
||||
|
||||
|
|
Loading…
Reference in New Issue