mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
[Attributor] Use the AANoNull attribute directly in AADereferenceable
Summary: Instead of constantly keeping track of the nonnull status with the dereferenceable information we can simply query the nonnull attribute whenever we need the information (debug + manifest). Reviewers: sstefan1, uenoku Subscribers: hiraditya, bollu, jfb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66113 llvm-svn: 368924
This commit is contained in:
parent
c97843653b
commit
1b61fbc6f8
@ -1297,9 +1297,6 @@ struct AADereferenceable
|
|||||||
/// Return true if we assume that the underlying value is nonnull.
|
/// Return true if we assume that the underlying value is nonnull.
|
||||||
virtual bool isAssumedNonNull() const = 0;
|
virtual bool isAssumedNonNull() const = 0;
|
||||||
|
|
||||||
/// Return true if we know that underlying value is nonnull.
|
|
||||||
virtual bool isKnownNonNull() const = 0;
|
|
||||||
|
|
||||||
/// Return true if we assume that underlying value is
|
/// Return true if we assume that underlying value is
|
||||||
/// dereferenceable(_or_null) globally.
|
/// dereferenceable(_or_null) globally.
|
||||||
virtual bool isAssumedGlobal() const = 0;
|
virtual bool isAssumedGlobal() const = 0;
|
||||||
|
@ -1609,35 +1609,29 @@ struct DerefState : AbstractState {
|
|||||||
/// State representing for dereferenceable bytes.
|
/// State representing for dereferenceable bytes.
|
||||||
IntegerState DerefBytesState;
|
IntegerState DerefBytesState;
|
||||||
|
|
||||||
/// State representing that whether the value is nonnull or global.
|
/// State representing that whether the value is globaly dereferenceable.
|
||||||
IntegerState NonNullGlobalState;
|
BooleanState GlobalState;
|
||||||
|
|
||||||
/// Bits encoding for NonNullGlobalState.
|
|
||||||
enum {
|
|
||||||
DEREF_NONNULL = 1 << 0,
|
|
||||||
DEREF_GLOBAL = 1 << 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// See AbstractState::isValidState()
|
/// See AbstractState::isValidState()
|
||||||
bool isValidState() const override { return DerefBytesState.isValidState(); }
|
bool isValidState() const override { return DerefBytesState.isValidState(); }
|
||||||
|
|
||||||
/// See AbstractState::isAtFixpoint()
|
/// See AbstractState::isAtFixpoint()
|
||||||
bool isAtFixpoint() const override {
|
bool isAtFixpoint() const override {
|
||||||
return !isValidState() || (DerefBytesState.isAtFixpoint() &&
|
return !isValidState() ||
|
||||||
NonNullGlobalState.isAtFixpoint());
|
(DerefBytesState.isAtFixpoint() && GlobalState.isAtFixpoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractState::indicateOptimisticFixpoint(...)
|
/// See AbstractState::indicateOptimisticFixpoint(...)
|
||||||
ChangeStatus indicateOptimisticFixpoint() override {
|
ChangeStatus indicateOptimisticFixpoint() override {
|
||||||
DerefBytesState.indicateOptimisticFixpoint();
|
DerefBytesState.indicateOptimisticFixpoint();
|
||||||
NonNullGlobalState.indicateOptimisticFixpoint();
|
GlobalState.indicateOptimisticFixpoint();
|
||||||
return ChangeStatus::UNCHANGED;
|
return ChangeStatus::UNCHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See AbstractState::indicatePessimisticFixpoint(...)
|
/// See AbstractState::indicatePessimisticFixpoint(...)
|
||||||
ChangeStatus indicatePessimisticFixpoint() override {
|
ChangeStatus indicatePessimisticFixpoint() override {
|
||||||
DerefBytesState.indicatePessimisticFixpoint();
|
DerefBytesState.indicatePessimisticFixpoint();
|
||||||
NonNullGlobalState.indicatePessimisticFixpoint();
|
GlobalState.indicatePessimisticFixpoint();
|
||||||
return ChangeStatus::CHANGED;
|
return ChangeStatus::CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1651,18 +1645,10 @@ struct DerefState : AbstractState {
|
|||||||
DerefBytesState.takeAssumedMinimum(Bytes);
|
DerefBytesState.takeAssumedMinimum(Bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update assumed NonNullGlobalState
|
|
||||||
void updateAssumedNonNullGlobalState(bool IsNonNull, bool IsGlobal) {
|
|
||||||
if (!IsNonNull)
|
|
||||||
NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
|
|
||||||
if (!IsGlobal)
|
|
||||||
NonNullGlobalState.removeAssumedBits(DEREF_GLOBAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Equality for DerefState.
|
/// Equality for DerefState.
|
||||||
bool operator==(const DerefState &R) {
|
bool operator==(const DerefState &R) {
|
||||||
return this->DerefBytesState == R.DerefBytesState &&
|
return this->DerefBytesState == R.DerefBytesState &&
|
||||||
this->NonNullGlobalState == R.NonNullGlobalState;
|
this->GlobalState == R.GlobalState;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1670,6 +1656,16 @@ struct AADereferenceableImpl : AADereferenceable, DerefState {
|
|||||||
AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
|
AADereferenceableImpl(const IRPosition &IRP) : AADereferenceable(IRP) {}
|
||||||
using StateType = DerefState;
|
using StateType = DerefState;
|
||||||
|
|
||||||
|
void initialize(Attributor &A) override {
|
||||||
|
SmallVector<Attribute, 4> Attrs;
|
||||||
|
getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
|
||||||
|
Attrs);
|
||||||
|
for (const Attribute &Attr : Attrs)
|
||||||
|
takeKnownDerefBytesMaximum(Attr.getValueAsInt());
|
||||||
|
|
||||||
|
NonNullAA = A.getAAFor<AANonNull>(*this, getIRPosition());
|
||||||
|
}
|
||||||
|
|
||||||
/// See AbstractAttribute::getState()
|
/// See AbstractAttribute::getState()
|
||||||
/// {
|
/// {
|
||||||
StateType &getState() override { return *this; }
|
StateType &getState() override { return *this; }
|
||||||
@ -1686,38 +1682,14 @@ struct AADereferenceableImpl : AADereferenceable, DerefState {
|
|||||||
return DerefBytesState.getKnown();
|
return DerefBytesState.getKnown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function for syncing nonnull state.
|
|
||||||
void syncNonNull(const AANonNull *NonNullAA) {
|
|
||||||
if (!NonNullAA) {
|
|
||||||
NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NonNullAA->isKnownNonNull())
|
|
||||||
NonNullGlobalState.addKnownBits(DEREF_NONNULL);
|
|
||||||
|
|
||||||
if (!NonNullAA->isAssumedNonNull())
|
|
||||||
NonNullGlobalState.removeAssumedBits(DEREF_NONNULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See AADereferenceable::isAssumedGlobal().
|
/// See AADereferenceable::isAssumedGlobal().
|
||||||
bool isAssumedGlobal() const override {
|
bool isAssumedGlobal() const override { return GlobalState.getAssumed(); }
|
||||||
return NonNullGlobalState.isAssumed(DEREF_GLOBAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See AADereferenceable::isKnownGlobal().
|
/// See AADereferenceable::isKnownGlobal().
|
||||||
bool isKnownGlobal() const override {
|
bool isKnownGlobal() const override { return GlobalState.getKnown(); }
|
||||||
return NonNullGlobalState.isKnown(DEREF_GLOBAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See AADereferenceable::isAssumedNonNull().
|
|
||||||
bool isAssumedNonNull() const override {
|
bool isAssumedNonNull() const override {
|
||||||
return NonNullGlobalState.isAssumed(DEREF_NONNULL);
|
return NonNullAA && NonNullAA->isAssumedNonNull();
|
||||||
}
|
|
||||||
|
|
||||||
/// See AADereferenceable::isKnownNonNull().
|
|
||||||
bool isKnownNonNull() const override {
|
|
||||||
return NonNullGlobalState.isKnown(DEREF_NONNULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void getDeducedAttributes(LLVMContext &Ctx,
|
void getDeducedAttributes(LLVMContext &Ctx,
|
||||||
@ -1731,15 +1703,7 @@ struct AADereferenceableImpl : AADereferenceable, DerefState {
|
|||||||
Ctx, getAssumedDereferenceableBytes()));
|
Ctx, getAssumedDereferenceableBytes()));
|
||||||
}
|
}
|
||||||
uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
|
uint64_t computeAssumedDerefenceableBytes(Attributor &A, Value &V,
|
||||||
bool &IsNonNull, bool &IsGlobal);
|
bool &IsGlobal);
|
||||||
|
|
||||||
void initialize(Attributor &A) override {
|
|
||||||
SmallVector<Attribute, 4> Attrs;
|
|
||||||
getAttrs({Attribute::Dereferenceable, Attribute::DereferenceableOrNull},
|
|
||||||
Attrs);
|
|
||||||
for (const Attribute &Attr : Attrs)
|
|
||||||
takeKnownDerefBytesMaximum(Attr.getValueAsInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See AbstractAttribute::getAsStr().
|
/// See AbstractAttribute::getAsStr().
|
||||||
const std::string getAsStr() const override {
|
const std::string getAsStr() const override {
|
||||||
@ -1751,6 +1715,9 @@ struct AADereferenceableImpl : AADereferenceable, DerefState {
|
|||||||
std::to_string(getKnownDereferenceableBytes()) + "-" +
|
std::to_string(getKnownDereferenceableBytes()) + "-" +
|
||||||
std::to_string(getAssumedDereferenceableBytes()) + ">";
|
std::to_string(getAssumedDereferenceableBytes()) + ">";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const AANonNull *NonNullAA = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AADereferenceableReturned final : AADereferenceableImpl {
|
struct AADereferenceableReturned final : AADereferenceableImpl {
|
||||||
@ -1774,15 +1741,15 @@ static uint64_t calcDifferenceIfBaseIsNonNull(int64_t DerefBytes,
|
|||||||
return std::max((int64_t)0, DerefBytes - Offset);
|
return std::max((int64_t)0, DerefBytes - Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
|
uint64_t
|
||||||
Attributor &A, Value &V, bool &IsNonNull, bool &IsGlobal) {
|
AADereferenceableImpl::computeAssumedDerefenceableBytes(Attributor &A, Value &V,
|
||||||
|
bool &IsGlobal) {
|
||||||
// TODO: Tracking the globally flag.
|
// TODO: Tracking the globally flag.
|
||||||
IsGlobal = false;
|
IsGlobal = false;
|
||||||
|
|
||||||
// First, we try to get information about V from Attributor.
|
// First, we try to get information about V from Attributor.
|
||||||
if (auto *DerefAA =
|
if (auto *DerefAA =
|
||||||
A.getAAFor<AADereferenceable>(*this, IRPosition::value(V))) {
|
A.getAAFor<AADereferenceable>(*this, IRPosition::value(V))) {
|
||||||
IsNonNull &= DerefAA->isAssumedNonNull();
|
|
||||||
return DerefAA->getAssumedDereferenceableBytes();
|
return DerefAA->getAssumedDereferenceableBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1795,7 +1762,6 @@ uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
|
|||||||
|
|
||||||
if (auto *BaseDerefAA =
|
if (auto *BaseDerefAA =
|
||||||
A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base))) {
|
A.getAAFor<AADereferenceable>(*this, IRPosition::value(*Base))) {
|
||||||
IsNonNull &= Offset != 0;
|
|
||||||
return calcDifferenceIfBaseIsNonNull(
|
return calcDifferenceIfBaseIsNonNull(
|
||||||
BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
|
BaseDerefAA->getAssumedDereferenceableBytes(), Offset.getSExtValue(),
|
||||||
Offset != 0 || BaseDerefAA->isAssumedNonNull());
|
Offset != 0 || BaseDerefAA->isAssumedNonNull());
|
||||||
@ -1810,26 +1776,22 @@ uint64_t AADereferenceableImpl::computeAssumedDerefenceableBytes(
|
|||||||
!NullPointerIsDefined(getAnchorScope(),
|
!NullPointerIsDefined(getAnchorScope(),
|
||||||
V.getType()->getPointerAddressSpace()));
|
V.getType()->getPointerAddressSpace()));
|
||||||
|
|
||||||
IsNonNull = false;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
|
ChangeStatus AADereferenceableReturned::updateImpl(Attributor &A) {
|
||||||
auto BeforeState = static_cast<DerefState>(*this);
|
auto BeforeState = static_cast<DerefState>(*this);
|
||||||
|
|
||||||
syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
|
|
||||||
|
|
||||||
bool IsNonNull = isAssumedNonNull();
|
|
||||||
bool IsGlobal = isAssumedGlobal();
|
bool IsGlobal = isAssumedGlobal();
|
||||||
|
|
||||||
auto CheckReturnValue = [&](Value &RV) -> bool {
|
auto CheckReturnValue = [&](Value &RV) -> bool {
|
||||||
takeAssumedDerefBytesMinimum(
|
takeAssumedDerefBytesMinimum(
|
||||||
computeAssumedDerefenceableBytes(A, RV, IsNonNull, IsGlobal));
|
computeAssumedDerefenceableBytes(A, RV, IsGlobal));
|
||||||
return isValidState();
|
return isValidState();
|
||||||
};
|
};
|
||||||
|
|
||||||
if (A.checkForAllReturnedValues(CheckReturnValue, *this)) {
|
if (A.checkForAllReturnedValues(CheckReturnValue, *this)) {
|
||||||
updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
|
GlobalState.intersectAssumedBits(IsGlobal);
|
||||||
return BeforeState == static_cast<DerefState>(*this)
|
return BeforeState == static_cast<DerefState>(*this)
|
||||||
? ChangeStatus::UNCHANGED
|
? ChangeStatus::UNCHANGED
|
||||||
: ChangeStatus::CHANGED;
|
: ChangeStatus::CHANGED;
|
||||||
@ -1857,9 +1819,6 @@ ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
|
|||||||
|
|
||||||
unsigned ArgNo = Arg.getArgNo();
|
unsigned ArgNo = Arg.getArgNo();
|
||||||
|
|
||||||
syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
|
|
||||||
|
|
||||||
bool IsNonNull = isAssumedNonNull();
|
|
||||||
bool IsGlobal = isAssumedGlobal();
|
bool IsGlobal = isAssumedGlobal();
|
||||||
|
|
||||||
// Callback function
|
// Callback function
|
||||||
@ -1874,14 +1833,13 @@ ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
|
|||||||
if (ICS && CS.getInstruction() == ICS.getInstruction()) {
|
if (ICS && CS.getInstruction() == ICS.getInstruction()) {
|
||||||
takeAssumedDerefBytesMinimum(
|
takeAssumedDerefBytesMinimum(
|
||||||
DereferenceableAA->getAssumedDereferenceableBytes());
|
DereferenceableAA->getAssumedDereferenceableBytes());
|
||||||
IsNonNull &= DereferenceableAA->isAssumedNonNull();
|
|
||||||
IsGlobal &= DereferenceableAA->isAssumedGlobal();
|
IsGlobal &= DereferenceableAA->isAssumedGlobal();
|
||||||
return isValidState();
|
return isValidState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
|
takeAssumedDerefBytesMinimum(computeAssumedDerefenceableBytes(
|
||||||
A, *CS.getArgOperand(ArgNo), IsNonNull, IsGlobal));
|
A, *CS.getArgOperand(ArgNo), IsGlobal));
|
||||||
|
|
||||||
return isValidState();
|
return isValidState();
|
||||||
};
|
};
|
||||||
@ -1889,7 +1847,7 @@ ChangeStatus AADereferenceableArgument::updateImpl(Attributor &A) {
|
|||||||
if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
|
if (!A.checkForAllCallSites(CallSiteCheck, *this, true))
|
||||||
return indicatePessimisticFixpoint();
|
return indicatePessimisticFixpoint();
|
||||||
|
|
||||||
updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
|
GlobalState.intersectAssumedBits(IsGlobal);
|
||||||
|
|
||||||
return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
|
return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
|
||||||
: ChangeStatus::CHANGED;
|
: ChangeStatus::CHANGED;
|
||||||
@ -1918,13 +1876,11 @@ ChangeStatus AADereferenceableCallSiteArgument::updateImpl(Attributor &A) {
|
|||||||
|
|
||||||
auto BeforeState = static_cast<DerefState>(*this);
|
auto BeforeState = static_cast<DerefState>(*this);
|
||||||
|
|
||||||
syncNonNull(A.getAAFor<AANonNull>(*this, getIRPosition()));
|
bool IsGlobal = isAssumedGlobal();
|
||||||
bool IsNonNull = isAssumedNonNull();
|
|
||||||
bool IsGlobal = isKnownGlobal();
|
|
||||||
|
|
||||||
takeAssumedDerefBytesMinimum(
|
takeAssumedDerefBytesMinimum(
|
||||||
computeAssumedDerefenceableBytes(A, V, IsNonNull, IsGlobal));
|
computeAssumedDerefenceableBytes(A, V, IsGlobal));
|
||||||
updateAssumedNonNullGlobalState(IsNonNull, IsGlobal);
|
GlobalState.intersectAssumedBits(IsGlobal);
|
||||||
|
|
||||||
return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
|
return BeforeState == static_cast<DerefState>(*this) ? ChangeStatus::UNCHANGED
|
||||||
: ChangeStatus::CHANGED;
|
: ChangeStatus::CHANGED;
|
||||||
|
Loading…
Reference in New Issue
Block a user