mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
[objc-arc] Extract out state specific to a ref count from the main objc arc sequence dataflow. This will allow me to separate the actual ARC queries from the meat of the dataflow algorithm.
llvm-svn: 231426
This commit is contained in:
parent
43db8da6a6
commit
2c056fffac
@ -9,6 +9,7 @@ add_llvm_library(LLVMObjCARCOpts
|
||||
DependencyAnalysis.cpp
|
||||
ProvenanceAnalysis.cpp
|
||||
ProvenanceAnalysisEvaluator.cpp
|
||||
PtrState.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/Transforms
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "ObjCARCAliasAnalysis.h"
|
||||
#include "ProvenanceAnalysis.h"
|
||||
#include "BlotMapVector.h"
|
||||
#include "PtrState.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -174,293 +175,6 @@ STATISTIC(NumReleasesAfterOpt,
|
||||
"Number of releases after optimization");
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
/// \enum Sequence
|
||||
///
|
||||
/// \brief A sequence of states that a pointer may go through in which an
|
||||
/// objc_retain and objc_release are actually needed.
|
||||
enum Sequence {
|
||||
S_None,
|
||||
S_Retain, ///< objc_retain(x).
|
||||
S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
|
||||
S_Use, ///< any use of x.
|
||||
S_Stop, ///< like S_Release, but code motion is stopped.
|
||||
S_Release, ///< objc_release(x).
|
||||
S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Sequence S)
|
||||
LLVM_ATTRIBUTE_UNUSED;
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Sequence S) {
|
||||
switch (S) {
|
||||
case S_None:
|
||||
return OS << "S_None";
|
||||
case S_Retain:
|
||||
return OS << "S_Retain";
|
||||
case S_CanRelease:
|
||||
return OS << "S_CanRelease";
|
||||
case S_Use:
|
||||
return OS << "S_Use";
|
||||
case S_Release:
|
||||
return OS << "S_Release";
|
||||
case S_MovableRelease:
|
||||
return OS << "S_MovableRelease";
|
||||
case S_Stop:
|
||||
return OS << "S_Stop";
|
||||
}
|
||||
llvm_unreachable("Unknown sequence type.");
|
||||
}
|
||||
}
|
||||
|
||||
static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
|
||||
// The easy cases.
|
||||
if (A == B)
|
||||
return A;
|
||||
if (A == S_None || B == S_None)
|
||||
return S_None;
|
||||
|
||||
if (A > B) std::swap(A, B);
|
||||
if (TopDown) {
|
||||
// Choose the side which is further along in the sequence.
|
||||
if ((A == S_Retain || A == S_CanRelease) &&
|
||||
(B == S_CanRelease || B == S_Use))
|
||||
return B;
|
||||
} else {
|
||||
// Choose the side which is further along in the sequence.
|
||||
if ((A == S_Use || A == S_CanRelease) &&
|
||||
(B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
|
||||
return A;
|
||||
// If both sides are releases, choose the more conservative one.
|
||||
if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
|
||||
return A;
|
||||
if (A == S_Release && B == S_MovableRelease)
|
||||
return A;
|
||||
}
|
||||
|
||||
return S_None;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// \brief Unidirectional information about either a
|
||||
/// retain-decrement-use-release sequence or release-use-decrement-retain
|
||||
/// reverse sequence.
|
||||
struct RRInfo {
|
||||
/// After an objc_retain, the reference count of the referenced
|
||||
/// object is known to be positive. Similarly, before an objc_release, the
|
||||
/// reference count of the referenced object is known to be positive. If
|
||||
/// there are retain-release pairs in code regions where the retain count
|
||||
/// is known to be positive, they can be eliminated, regardless of any side
|
||||
/// effects between them.
|
||||
///
|
||||
/// Also, a retain+release pair nested within another retain+release
|
||||
/// pair all on the known same pointer value can be eliminated, regardless
|
||||
/// of any intervening side effects.
|
||||
///
|
||||
/// KnownSafe is true when either of these conditions is satisfied.
|
||||
bool KnownSafe;
|
||||
|
||||
/// True of the objc_release calls are all marked with the "tail" keyword.
|
||||
bool IsTailCallRelease;
|
||||
|
||||
/// If the Calls are objc_release calls and they all have a
|
||||
/// clang.imprecise_release tag, this is the metadata tag.
|
||||
MDNode *ReleaseMetadata;
|
||||
|
||||
/// For a top-down sequence, the set of objc_retains or
|
||||
/// objc_retainBlocks. For bottom-up, the set of objc_releases.
|
||||
SmallPtrSet<Instruction *, 2> Calls;
|
||||
|
||||
/// The set of optimal insert positions for moving calls in the opposite
|
||||
/// sequence.
|
||||
SmallPtrSet<Instruction *, 2> ReverseInsertPts;
|
||||
|
||||
/// If this is true, we cannot perform code motion but can still remove
|
||||
/// retain/release pairs.
|
||||
bool CFGHazardAfflicted;
|
||||
|
||||
RRInfo() :
|
||||
KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(nullptr),
|
||||
CFGHazardAfflicted(false) {}
|
||||
|
||||
void clear();
|
||||
|
||||
/// Conservatively merge the two RRInfo. Returns true if a partial merge has
|
||||
/// occurred, false otherwise.
|
||||
bool Merge(const RRInfo &Other);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
void RRInfo::clear() {
|
||||
KnownSafe = false;
|
||||
IsTailCallRelease = false;
|
||||
ReleaseMetadata = nullptr;
|
||||
Calls.clear();
|
||||
ReverseInsertPts.clear();
|
||||
CFGHazardAfflicted = false;
|
||||
}
|
||||
|
||||
bool RRInfo::Merge(const RRInfo &Other) {
|
||||
// Conservatively merge the ReleaseMetadata information.
|
||||
if (ReleaseMetadata != Other.ReleaseMetadata)
|
||||
ReleaseMetadata = nullptr;
|
||||
|
||||
// Conservatively merge the boolean state.
|
||||
KnownSafe &= Other.KnownSafe;
|
||||
IsTailCallRelease &= Other.IsTailCallRelease;
|
||||
CFGHazardAfflicted |= Other.CFGHazardAfflicted;
|
||||
|
||||
// Merge the call sets.
|
||||
Calls.insert(Other.Calls.begin(), Other.Calls.end());
|
||||
|
||||
// Merge the insert point sets. If there are any differences,
|
||||
// that makes this a partial merge.
|
||||
bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
|
||||
for (Instruction *Inst : Other.ReverseInsertPts)
|
||||
Partial |= ReverseInsertPts.insert(Inst).second;
|
||||
return Partial;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// \brief This class summarizes several per-pointer runtime properties which
|
||||
/// are propogated through the flow graph.
|
||||
class PtrState {
|
||||
/// True if the reference count is known to be incremented.
|
||||
bool KnownPositiveRefCount;
|
||||
|
||||
/// True if we've seen an opportunity for partial RR elimination, such as
|
||||
/// pushing calls into a CFG triangle or into one side of a CFG diamond.
|
||||
bool Partial;
|
||||
|
||||
/// The current position in the sequence.
|
||||
unsigned char Seq : 8;
|
||||
|
||||
/// Unidirectional information about the current sequence.
|
||||
RRInfo RRI;
|
||||
|
||||
public:
|
||||
PtrState() : KnownPositiveRefCount(false), Partial(false),
|
||||
Seq(S_None) {}
|
||||
|
||||
|
||||
bool IsKnownSafe() const {
|
||||
return RRI.KnownSafe;
|
||||
}
|
||||
|
||||
void SetKnownSafe(const bool NewValue) {
|
||||
RRI.KnownSafe = NewValue;
|
||||
}
|
||||
|
||||
bool IsTailCallRelease() const {
|
||||
return RRI.IsTailCallRelease;
|
||||
}
|
||||
|
||||
void SetTailCallRelease(const bool NewValue) {
|
||||
RRI.IsTailCallRelease = NewValue;
|
||||
}
|
||||
|
||||
bool IsTrackingImpreciseReleases() const {
|
||||
return RRI.ReleaseMetadata != nullptr;
|
||||
}
|
||||
|
||||
const MDNode *GetReleaseMetadata() const {
|
||||
return RRI.ReleaseMetadata;
|
||||
}
|
||||
|
||||
void SetReleaseMetadata(MDNode *NewValue) {
|
||||
RRI.ReleaseMetadata = NewValue;
|
||||
}
|
||||
|
||||
bool IsCFGHazardAfflicted() const {
|
||||
return RRI.CFGHazardAfflicted;
|
||||
}
|
||||
|
||||
void SetCFGHazardAfflicted(const bool NewValue) {
|
||||
RRI.CFGHazardAfflicted = NewValue;
|
||||
}
|
||||
|
||||
void SetKnownPositiveRefCount() {
|
||||
DEBUG(dbgs() << "Setting Known Positive.\n");
|
||||
KnownPositiveRefCount = true;
|
||||
}
|
||||
|
||||
void ClearKnownPositiveRefCount() {
|
||||
DEBUG(dbgs() << "Clearing Known Positive.\n");
|
||||
KnownPositiveRefCount = false;
|
||||
}
|
||||
|
||||
bool HasKnownPositiveRefCount() const {
|
||||
return KnownPositiveRefCount;
|
||||
}
|
||||
|
||||
void SetSeq(Sequence NewSeq) {
|
||||
DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
|
||||
Seq = NewSeq;
|
||||
}
|
||||
|
||||
Sequence GetSeq() const {
|
||||
return static_cast<Sequence>(Seq);
|
||||
}
|
||||
|
||||
void ClearSequenceProgress() {
|
||||
ResetSequenceProgress(S_None);
|
||||
}
|
||||
|
||||
void ResetSequenceProgress(Sequence NewSeq) {
|
||||
DEBUG(dbgs() << "Resetting sequence progress.\n");
|
||||
SetSeq(NewSeq);
|
||||
Partial = false;
|
||||
RRI.clear();
|
||||
}
|
||||
|
||||
void Merge(const PtrState &Other, bool TopDown);
|
||||
|
||||
void InsertCall(Instruction *I) {
|
||||
RRI.Calls.insert(I);
|
||||
}
|
||||
|
||||
void InsertReverseInsertPt(Instruction *I) {
|
||||
RRI.ReverseInsertPts.insert(I);
|
||||
}
|
||||
|
||||
void ClearReverseInsertPts() {
|
||||
RRI.ReverseInsertPts.clear();
|
||||
}
|
||||
|
||||
bool HasReverseInsertPts() const {
|
||||
return !RRI.ReverseInsertPts.empty();
|
||||
}
|
||||
|
||||
const RRInfo &GetRRInfo() const {
|
||||
return RRI;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void
|
||||
PtrState::Merge(const PtrState &Other, bool TopDown) {
|
||||
Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
|
||||
KnownPositiveRefCount &= Other.KnownPositiveRefCount;
|
||||
|
||||
// If we're not in a sequence (anymore), drop all associated state.
|
||||
if (Seq == S_None) {
|
||||
Partial = false;
|
||||
RRI.clear();
|
||||
} else if (Partial || Other.Partial) {
|
||||
// If we're doing a merge on a path that's previously seen a partial
|
||||
// merge, conservatively drop the sequence, to avoid doing partial
|
||||
// RR elimination. If the branch predicates for the two merge differ,
|
||||
// mixing them is unsafe.
|
||||
ClearSequenceProgress();
|
||||
} else {
|
||||
// Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
|
||||
// point, we know that currently we are not partial. Stash whether or not
|
||||
// the merge operation caused us to undergo a partial merging of reverse
|
||||
// insertion points.
|
||||
Partial = RRI.Merge(Other.RRI);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// \brief Per-BasicBlock state.
|
||||
class BBState {
|
||||
|
115
lib/Transforms/ObjCARC/PtrState.cpp
Normal file
115
lib/Transforms/ObjCARC/PtrState.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
//===--- PtrState.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PtrState.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::objcarc;
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const Sequence S) {
|
||||
switch (S) {
|
||||
case S_None:
|
||||
return OS << "S_None";
|
||||
case S_Retain:
|
||||
return OS << "S_Retain";
|
||||
case S_CanRelease:
|
||||
return OS << "S_CanRelease";
|
||||
case S_Use:
|
||||
return OS << "S_Use";
|
||||
case S_Release:
|
||||
return OS << "S_Release";
|
||||
case S_MovableRelease:
|
||||
return OS << "S_MovableRelease";
|
||||
case S_Stop:
|
||||
return OS << "S_Stop";
|
||||
}
|
||||
llvm_unreachable("Unknown sequence type.");
|
||||
}
|
||||
|
||||
static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
|
||||
// The easy cases.
|
||||
if (A == B)
|
||||
return A;
|
||||
if (A == S_None || B == S_None)
|
||||
return S_None;
|
||||
|
||||
if (A > B)
|
||||
std::swap(A, B);
|
||||
if (TopDown) {
|
||||
// Choose the side which is further along in the sequence.
|
||||
if ((A == S_Retain || A == S_CanRelease) &&
|
||||
(B == S_CanRelease || B == S_Use))
|
||||
return B;
|
||||
} else {
|
||||
// Choose the side which is further along in the sequence.
|
||||
if ((A == S_Use || A == S_CanRelease) &&
|
||||
(B == S_Use || B == S_Release || B == S_Stop || B == S_MovableRelease))
|
||||
return A;
|
||||
// If both sides are releases, choose the more conservative one.
|
||||
if (A == S_Stop && (B == S_Release || B == S_MovableRelease))
|
||||
return A;
|
||||
if (A == S_Release && B == S_MovableRelease)
|
||||
return A;
|
||||
}
|
||||
|
||||
return S_None;
|
||||
}
|
||||
|
||||
void RRInfo::clear() {
|
||||
KnownSafe = false;
|
||||
IsTailCallRelease = false;
|
||||
ReleaseMetadata = nullptr;
|
||||
Calls.clear();
|
||||
ReverseInsertPts.clear();
|
||||
CFGHazardAfflicted = false;
|
||||
}
|
||||
|
||||
bool RRInfo::Merge(const RRInfo &Other) {
|
||||
// Conservatively merge the ReleaseMetadata information.
|
||||
if (ReleaseMetadata != Other.ReleaseMetadata)
|
||||
ReleaseMetadata = nullptr;
|
||||
|
||||
// Conservatively merge the boolean state.
|
||||
KnownSafe &= Other.KnownSafe;
|
||||
IsTailCallRelease &= Other.IsTailCallRelease;
|
||||
CFGHazardAfflicted |= Other.CFGHazardAfflicted;
|
||||
|
||||
// Merge the call sets.
|
||||
Calls.insert(Other.Calls.begin(), Other.Calls.end());
|
||||
|
||||
// Merge the insert point sets. If there are any differences,
|
||||
// that makes this a partial merge.
|
||||
bool Partial = ReverseInsertPts.size() != Other.ReverseInsertPts.size();
|
||||
for (Instruction *Inst : Other.ReverseInsertPts)
|
||||
Partial |= ReverseInsertPts.insert(Inst).second;
|
||||
return Partial;
|
||||
}
|
||||
|
||||
void PtrState::Merge(const PtrState &Other, bool TopDown) {
|
||||
Seq = MergeSeqs(GetSeq(), Other.GetSeq(), TopDown);
|
||||
KnownPositiveRefCount &= Other.KnownPositiveRefCount;
|
||||
|
||||
// If we're not in a sequence (anymore), drop all associated state.
|
||||
if (Seq == S_None) {
|
||||
Partial = false;
|
||||
RRI.clear();
|
||||
} else if (Partial || Other.Partial) {
|
||||
// If we're doing a merge on a path that's previously seen a partial
|
||||
// merge, conservatively drop the sequence, to avoid doing partial
|
||||
// RR elimination. If the branch predicates for the two merge differ,
|
||||
// mixing them is unsafe.
|
||||
ClearSequenceProgress();
|
||||
} else {
|
||||
// Otherwise merge the other PtrState's RRInfo into our RRInfo. At this
|
||||
// point, we know that currently we are not partial. Stash whether or not
|
||||
// the merge operation caused us to undergo a partial merging of reverse
|
||||
// insertion points.
|
||||
Partial = RRI.Merge(Other.RRI);
|
||||
}
|
||||
}
|
181
lib/Transforms/ObjCARC/PtrState.h
Normal file
181
lib/Transforms/ObjCARC/PtrState.h
Normal file
@ -0,0 +1,181 @@
|
||||
//===--- PtrState.h - ARC State for a Ptr -------------------*- C++ -*-----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains declarations for the ARC state associated with a ptr. It
|
||||
// is only used by the ARC Sequence Dataflow computation. By separating this
|
||||
// from the actual dataflow, it is easier to consider the mechanics of the ARC
|
||||
// optimization separate from the actual predicates being used.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
|
||||
#define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
|
||||
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Value.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
namespace llvm {
|
||||
namespace objcarc {
|
||||
|
||||
/// \enum Sequence
|
||||
///
|
||||
/// \brief A sequence of states that a pointer may go through in which an
|
||||
/// objc_retain and objc_release are actually needed.
|
||||
enum Sequence {
|
||||
S_None,
|
||||
S_Retain, ///< objc_retain(x).
|
||||
S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.
|
||||
S_Use, ///< any use of x.
|
||||
S_Stop, ///< like S_Release, but code motion is stopped.
|
||||
S_Release, ///< objc_release(x).
|
||||
S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
|
||||
};
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS,
|
||||
const Sequence S) LLVM_ATTRIBUTE_UNUSED;
|
||||
|
||||
/// \brief Unidirectional information about either a
|
||||
/// retain-decrement-use-release sequence or release-use-decrement-retain
|
||||
/// reverse sequence.
|
||||
struct RRInfo {
|
||||
/// After an objc_retain, the reference count of the referenced
|
||||
/// object is known to be positive. Similarly, before an objc_release, the
|
||||
/// reference count of the referenced object is known to be positive. If
|
||||
/// there are retain-release pairs in code regions where the retain count
|
||||
/// is known to be positive, they can be eliminated, regardless of any side
|
||||
/// effects between them.
|
||||
///
|
||||
/// Also, a retain+release pair nested within another retain+release
|
||||
/// pair all on the known same pointer value can be eliminated, regardless
|
||||
/// of any intervening side effects.
|
||||
///
|
||||
/// KnownSafe is true when either of these conditions is satisfied.
|
||||
bool KnownSafe;
|
||||
|
||||
/// True of the objc_release calls are all marked with the "tail" keyword.
|
||||
bool IsTailCallRelease;
|
||||
|
||||
/// If the Calls are objc_release calls and they all have a
|
||||
/// clang.imprecise_release tag, this is the metadata tag.
|
||||
MDNode *ReleaseMetadata;
|
||||
|
||||
/// For a top-down sequence, the set of objc_retains or
|
||||
/// objc_retainBlocks. For bottom-up, the set of objc_releases.
|
||||
SmallPtrSet<Instruction *, 2> Calls;
|
||||
|
||||
/// The set of optimal insert positions for moving calls in the opposite
|
||||
/// sequence.
|
||||
SmallPtrSet<Instruction *, 2> ReverseInsertPts;
|
||||
|
||||
/// If this is true, we cannot perform code motion but can still remove
|
||||
/// retain/release pairs.
|
||||
bool CFGHazardAfflicted;
|
||||
|
||||
RRInfo()
|
||||
: KnownSafe(false), IsTailCallRelease(false), ReleaseMetadata(nullptr),
|
||||
CFGHazardAfflicted(false) {}
|
||||
|
||||
void clear();
|
||||
|
||||
/// Conservatively merge the two RRInfo. Returns true if a partial merge has
|
||||
/// occurred, false otherwise.
|
||||
bool Merge(const RRInfo &Other);
|
||||
};
|
||||
|
||||
/// \brief This class summarizes several per-pointer runtime properties which
|
||||
/// are propogated through the flow graph.
|
||||
class PtrState {
|
||||
/// True if the reference count is known to be incremented.
|
||||
bool KnownPositiveRefCount;
|
||||
|
||||
/// True if we've seen an opportunity for partial RR elimination, such as
|
||||
/// pushing calls into a CFG triangle or into one side of a CFG diamond.
|
||||
bool Partial;
|
||||
|
||||
/// The current position in the sequence.
|
||||
unsigned char Seq : 8;
|
||||
|
||||
/// Unidirectional information about the current sequence.
|
||||
RRInfo RRI;
|
||||
|
||||
public:
|
||||
PtrState() : KnownPositiveRefCount(false), Partial(false), Seq(S_None) {}
|
||||
|
||||
bool IsKnownSafe() const { return RRI.KnownSafe; }
|
||||
|
||||
void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }
|
||||
|
||||
bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }
|
||||
|
||||
void SetTailCallRelease(const bool NewValue) {
|
||||
RRI.IsTailCallRelease = NewValue;
|
||||
}
|
||||
|
||||
bool IsTrackingImpreciseReleases() const {
|
||||
return RRI.ReleaseMetadata != nullptr;
|
||||
}
|
||||
|
||||
const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }
|
||||
|
||||
void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }
|
||||
|
||||
bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }
|
||||
|
||||
void SetCFGHazardAfflicted(const bool NewValue) {
|
||||
RRI.CFGHazardAfflicted = NewValue;
|
||||
}
|
||||
|
||||
void SetKnownPositiveRefCount() {
|
||||
DEBUG(dbgs() << "Setting Known Positive.\n");
|
||||
KnownPositiveRefCount = true;
|
||||
}
|
||||
|
||||
void ClearKnownPositiveRefCount() {
|
||||
DEBUG(dbgs() << "Clearing Known Positive.\n");
|
||||
KnownPositiveRefCount = false;
|
||||
}
|
||||
|
||||
bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
|
||||
|
||||
void SetSeq(Sequence NewSeq) {
|
||||
DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
|
||||
Seq = NewSeq;
|
||||
}
|
||||
|
||||
Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
|
||||
|
||||
void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
|
||||
|
||||
void ResetSequenceProgress(Sequence NewSeq) {
|
||||
DEBUG(dbgs() << "Resetting sequence progress.\n");
|
||||
SetSeq(NewSeq);
|
||||
Partial = false;
|
||||
RRI.clear();
|
||||
}
|
||||
|
||||
void Merge(const PtrState &Other, bool TopDown);
|
||||
|
||||
void InsertCall(Instruction *I) { RRI.Calls.insert(I); }
|
||||
|
||||
void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }
|
||||
|
||||
void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }
|
||||
|
||||
bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }
|
||||
|
||||
const RRInfo &GetRRInfo() const { return RRI; }
|
||||
};
|
||||
|
||||
} // end namespace objcarc
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user