1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00

[Attributor][NFCI] Improve the usage of IntegerStates

Setting the upper bound directly in the state can be beneficial and
simplifies the logic. This also exposed more copy&paste type errors.
This commit is contained in:
Johannes Doerfert 2019-10-29 23:18:49 -05:00
parent ec80dede68
commit 7dda5a3585
3 changed files with 48 additions and 42 deletions

View File

@ -1146,24 +1146,27 @@ protected:
}; };
/// Specialization of the integer state for a bit-wise encoding. /// Specialization of the integer state for a bit-wise encoding.
struct BitIntegerState : public IntegerStateBase<uint32_t, ~0u, 0> { template <typename base_ty = uint32_t, base_ty BestState = ~base_ty(0),
using base_t = IntegerStateBase::base_t; base_ty WorstState = 0>
struct BitIntegerState
: public IntegerStateBase<base_ty, BestState, WorstState> {
using base_t = base_ty;
/// Return true if the bits set in \p BitsEncoding are "known bits". /// Return true if the bits set in \p BitsEncoding are "known bits".
bool isKnown(base_t BitsEncoding) const { bool isKnown(base_t BitsEncoding) const {
return (Known & BitsEncoding) == BitsEncoding; return (this->Known & BitsEncoding) == BitsEncoding;
} }
/// Return true if the bits set in \p BitsEncoding are "assumed bits". /// Return true if the bits set in \p BitsEncoding are "assumed bits".
bool isAssumed(base_t BitsEncoding) const { bool isAssumed(base_t BitsEncoding) const {
return (Assumed & BitsEncoding) == BitsEncoding; return (this->Assumed & BitsEncoding) == BitsEncoding;
} }
/// Add the bits in \p BitsEncoding to the "known bits". /// Add the bits in \p BitsEncoding to the "known bits".
BitIntegerState &addKnownBits(base_t Bits) { BitIntegerState &addKnownBits(base_t Bits) {
// Make sure we never miss any "known bits". // Make sure we never miss any "known bits".
Assumed |= Bits; this->Assumed |= Bits;
Known |= Bits; this->Known |= Bits;
return *this; return *this;
} }
@ -1174,14 +1177,14 @@ struct BitIntegerState : public IntegerStateBase<uint32_t, ~0u, 0> {
/// Remove the bits in \p BitsEncoding from the "known bits". /// Remove the bits in \p BitsEncoding from the "known bits".
BitIntegerState &removeKnownBits(base_t BitsEncoding) { BitIntegerState &removeKnownBits(base_t BitsEncoding) {
Known = (Known & ~BitsEncoding); this->Known = (this->Known & ~BitsEncoding);
return *this; return *this;
} }
/// Keep only "assumed bits" also set in \p BitsEncoding but all known ones. /// Keep only "assumed bits" also set in \p BitsEncoding but all known ones.
BitIntegerState &intersectAssumedBits(base_t BitsEncoding) { BitIntegerState &intersectAssumedBits(base_t BitsEncoding) {
// Make sure we never loose any "known bits". // Make sure we never loose any "known bits".
Assumed = (Assumed & BitsEncoding) | Known; this->Assumed = (this->Assumed & BitsEncoding) | this->Known;
return *this; return *this;
} }
@ -1191,32 +1194,35 @@ private:
} }
void handleNewKnownValue(base_t Value) override { addKnownBits(Value); } void handleNewKnownValue(base_t Value) override { addKnownBits(Value); }
void joinOR(base_t AssumedValue, base_t KnownValue) override { void joinOR(base_t AssumedValue, base_t KnownValue) override {
Known |= KnownValue; this->Known |= KnownValue;
Assumed |= AssumedValue; this->Assumed |= AssumedValue;
} }
void joinAND(base_t AssumedValue, base_t KnownValue) override { void joinAND(base_t AssumedValue, base_t KnownValue) override {
Known &= KnownValue; this->Known &= KnownValue;
Assumed &= AssumedValue; this->Assumed &= AssumedValue;
} }
}; };
/// Specialization of the integer state for an increasing value, hence ~0u is /// Specialization of the integer state for an increasing value, hence ~0u is
/// the best state and 0 the worst. /// the best state and 0 the worst.
struct IncIntegerState : public IntegerStateBase<uint32_t, ~0u, 0> { template <typename base_ty = uint32_t, base_ty BestState = ~base_ty(0),
using base_t = IntegerStateBase::base_t; base_ty WorstState = 0>
struct IncIntegerState
: public IntegerStateBase<base_ty, BestState, WorstState> {
using base_t = base_ty;
/// Take minimum of assumed and \p Value. /// Take minimum of assumed and \p Value.
IncIntegerState &takeAssumedMinimum(base_t Value) { IncIntegerState &takeAssumedMinimum(base_t Value) {
// Make sure we never loose "known value". // Make sure we never loose "known value".
Assumed = std::max(std::min(Assumed, Value), Known); this->Assumed = std::max(std::min(this->Assumed, Value), this->Known);
return *this; return *this;
} }
/// Take maximum of known and \p Value. /// Take maximum of known and \p Value.
IncIntegerState &takeKnownMaximum(base_t Value) { IncIntegerState &takeKnownMaximum(base_t Value) {
// Make sure we never loose "known value". // Make sure we never loose "known value".
Assumed = std::max(Value, Assumed); this->Assumed = std::max(Value, this->Assumed);
Known = std::max(Value, Known); this->Known = std::max(Value, this->Known);
return *this; return *this;
} }
@ -1226,12 +1232,12 @@ private:
} }
void handleNewKnownValue(base_t Value) override { takeKnownMaximum(Value); } void handleNewKnownValue(base_t Value) override { takeKnownMaximum(Value); }
void joinOR(base_t AssumedValue, base_t KnownValue) override { void joinOR(base_t AssumedValue, base_t KnownValue) override {
Known = std::max(Known, KnownValue); this->Known = std::max(this->Known, KnownValue);
Assumed = std::max(Assumed, AssumedValue); this->Assumed = std::max(this->Assumed, AssumedValue);
} }
void joinAND(base_t AssumedValue, base_t KnownValue) override { void joinAND(base_t AssumedValue, base_t KnownValue) override {
Known = std::min(Known, KnownValue); this->Known = std::min(this->Known, KnownValue);
Assumed = std::min(Assumed, AssumedValue); this->Assumed = std::min(this->Assumed, AssumedValue);
} }
}; };
@ -1752,7 +1758,7 @@ struct AAIsDead : public StateWrapper<BooleanState, AbstractAttribute>,
struct DerefState : AbstractState { struct DerefState : AbstractState {
/// State representing for dereferenceable bytes. /// State representing for dereferenceable bytes.
IncIntegerState DerefBytesState; IncIntegerState<> DerefBytesState;
/// State representing that whether the value is globaly dereferenceable. /// State representing that whether the value is globaly dereferenceable.
BooleanState GlobalState; BooleanState GlobalState;
@ -1866,10 +1872,12 @@ struct AADereferenceable
static const char ID; static const char ID;
}; };
using AAAlignmentStateType =
IncIntegerState<uint32_t, /* maximal alignment */ 1U << 29, 0>;
/// An abstract interface for all align attributes. /// An abstract interface for all align attributes.
struct AAAlign struct AAAlign : public IRAttribute<
: public IRAttribute<Attribute::Alignment, Attribute::Alignment,
StateWrapper<IncIntegerState, AbstractAttribute>> { StateWrapper<AAAlignmentStateType, AbstractAttribute>> {
AAAlign(const IRPosition &IRP) : IRAttribute(IRP) {} AAAlign(const IRPosition &IRP) : IRAttribute(IRP) {}
/// Return assumed alignment. /// Return assumed alignment.
@ -1887,8 +1895,9 @@ struct AAAlign
/// An abstract interface for all nocapture attributes. /// An abstract interface for all nocapture attributes.
struct AANoCapture struct AANoCapture
: public IRAttribute<Attribute::NoCapture, : public IRAttribute<
StateWrapper<BitIntegerState, AbstractAttribute>> { Attribute::NoCapture,
StateWrapper<BitIntegerState<uint16_t, 7, 0>, AbstractAttribute>> {
AANoCapture(const IRPosition &IRP) : IRAttribute(IRP) {} AANoCapture(const IRPosition &IRP) : IRAttribute(IRP) {}
/// State encoding bits. A set bit in the state means the property holds. /// State encoding bits. A set bit in the state means the property holds.
@ -1978,8 +1987,9 @@ struct AAHeapToStack : public StateWrapper<BooleanState, AbstractAttribute>,
/// An abstract interface for all memory related attributes. /// An abstract interface for all memory related attributes.
struct AAMemoryBehavior struct AAMemoryBehavior
: public IRAttribute<Attribute::ReadNone, : public IRAttribute<
StateWrapper<BitIntegerState, AbstractAttribute>> { Attribute::ReadNone,
StateWrapper<BitIntegerState<uint8_t, 3>, AbstractAttribute>> {
AAMemoryBehavior(const IRPosition &IRP) : IRAttribute(IRP) {} AAMemoryBehavior(const IRPosition &IRP) : IRAttribute(IRP) {}
/// State encoding bits. A set bit in the state means the property holds. /// State encoding bits. A set bit in the state means the property holds.

View File

@ -2700,10 +2700,9 @@ struct AAIsDeadCallSite final : AAIsDeadFunction {
template <> template <>
ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S, ChangeStatus clampStateAndIndicateChange<DerefState>(DerefState &S,
const DerefState &R) { const DerefState &R) {
ChangeStatus CS0 = clampStateAndIndicateChange<IncIntegerState>( ChangeStatus CS0 =
S.DerefBytesState, R.DerefBytesState); clampStateAndIndicateChange(S.DerefBytesState, R.DerefBytesState);
ChangeStatus CS1 = ChangeStatus CS1 = clampStateAndIndicateChange(S.GlobalState, R.GlobalState);
clampStateAndIndicateChange<BooleanState>(S.GlobalState, R.GlobalState);
return CS0 | CS1; return CS0 | CS1;
} }
@ -2926,13 +2925,8 @@ struct AADereferenceableCallSiteReturned final
struct AAAlignImpl : AAAlign { struct AAAlignImpl : AAAlign {
AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {} AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
// Max alignemnt value allowed in IR
static const unsigned MAX_ALIGN = 1U << 29;
/// See AbstractAttribute::initialize(...). /// See AbstractAttribute::initialize(...).
void initialize(Attributor &A) override { void initialize(Attributor &A) override {
takeAssumedMinimum(MAX_ALIGN);
SmallVector<Attribute, 4> Attrs; SmallVector<Attribute, 4> Attrs;
getAttrs({Attribute::Alignment}, Attrs); getAttrs({Attribute::Alignment}, Attrs);
for (const Attribute &Attr : Attrs) for (const Attribute &Attr : Attrs)
@ -3273,7 +3267,7 @@ struct AACaptureUseTracker final : public CaptureTracker {
/// the search is stopped with \p CapturedInMemory and \p CapturedInInteger /// the search is stopped with \p CapturedInMemory and \p CapturedInInteger
/// conservatively set to true. /// conservatively set to true.
AACaptureUseTracker(Attributor &A, AANoCapture &NoCaptureAA, AACaptureUseTracker(Attributor &A, AANoCapture &NoCaptureAA,
const AAIsDead &IsDeadAA, BitIntegerState &State, const AAIsDead &IsDeadAA, AANoCapture::StateType &State,
SmallVectorImpl<const Value *> &PotentialCopies, SmallVectorImpl<const Value *> &PotentialCopies,
unsigned &RemainingUsesToExplore) unsigned &RemainingUsesToExplore)
: A(A), NoCaptureAA(NoCaptureAA), IsDeadAA(IsDeadAA), State(State), : A(A), NoCaptureAA(NoCaptureAA), IsDeadAA(IsDeadAA), State(State),
@ -3392,7 +3386,7 @@ private:
const AAIsDead &IsDeadAA; const AAIsDead &IsDeadAA;
/// The state currently updated. /// The state currently updated.
BitIntegerState &State; AANoCapture::StateType &State;
/// Set of potential copies of the tracked value. /// Set of potential copies of the tracked value.
SmallVectorImpl<const Value *> &PotentialCopies; SmallVectorImpl<const Value *> &PotentialCopies;
@ -3478,6 +3472,8 @@ ChangeStatus AANoCaptureImpl::updateImpl(Attributor &A) {
AANoCapture::StateType &S = getState(); AANoCapture::StateType &S = getState();
auto Assumed = S.getAssumed(); auto Assumed = S.getAssumed();
S.intersectAssumedBits(T.getAssumed()); S.intersectAssumedBits(T.getAssumed());
if (!isAssumedNoCaptureMaybeReturned())
return indicatePessimisticFixpoint();
return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED return Assumed == S.getAssumed() ? ChangeStatus::UNCHANGED
: ChangeStatus::CHANGED; : ChangeStatus::CHANGED;
} }
@ -4220,7 +4216,7 @@ struct AAMemoryBehaviorCallSiteArgument final : AAMemoryBehaviorArgument {
auto &ArgAA = A.getAAFor<AAMemoryBehavior>(*this, ArgPos); auto &ArgAA = A.getAAFor<AAMemoryBehavior>(*this, ArgPos);
return clampStateAndIndicateChange( return clampStateAndIndicateChange(
getState(), getState(),
static_cast<const AANoCapture::StateType &>(ArgAA.getState())); static_cast<const AAMemoryBehavior::StateType &>(ArgAA.getState()));
} }
/// See AbstractAttribute::trackStatistics() /// See AbstractAttribute::trackStatistics()

View File

@ -1,4 +1,4 @@
; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=8 -S < %s | FileCheck %s ; RUN: opt -functionattrs -enable-nonnull-arg-prop -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 -S < %s | FileCheck %s
; ;
; This is an evolved example to stress test SCC parameter attribute propagation. ; This is an evolved example to stress test SCC parameter attribute propagation.
; The SCC in this test is made up of the following six function, three of which ; The SCC in this test is made up of the following six function, three of which