123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- //===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // 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/Analysis/ObjCARCInstKind.h"
- #include "llvm/Support/Compiler.h"
- namespace llvm {
- class BasicBlock;
- class Instruction;
- class MDNode;
- class raw_ostream;
- class Value;
- namespace objcarc {
- class ARCMDKindCache;
- class BundledRetainClaimRVs;
- class ProvenanceAnalysis;
- /// \enum Sequence
- ///
- /// 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, ///< code motion is stopped.
- S_MovableRelease ///< objc_release(x), !clang.imprecise_release.
- };
- raw_ostream &operator<<(raw_ostream &OS,
- const Sequence S) LLVM_ATTRIBUTE_UNUSED;
- /// 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 = false;
- /// True of the objc_release calls are all marked with the "tail" keyword.
- bool IsTailCallRelease = false;
- /// If the Calls are objc_release calls and they all have a
- /// clang.imprecise_release tag, this is the metadata tag.
- MDNode *ReleaseMetadata = nullptr;
- /// 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 = false;
- RRInfo() = default;
- void clear();
- /// Conservatively merge the two RRInfo. Returns true if a partial merge has
- /// occurred, false otherwise.
- bool Merge(const RRInfo &Other);
- };
- /// This class summarizes several per-pointer runtime properties which
- /// are propagated through the flow graph.
- class PtrState {
- protected:
- /// True if the reference count is known to be incremented.
- bool KnownPositiveRefCount = false;
- /// 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 = false;
- /// The current position in the sequence.
- unsigned char Seq : 8;
- /// Unidirectional information about the current sequence.
- RRInfo RRI;
- PtrState() : Seq(S_None) {}
- public:
- 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();
- void ClearKnownPositiveRefCount();
- bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }
- void SetSeq(Sequence NewSeq);
- Sequence GetSeq() const { return static_cast<Sequence>(Seq); }
- void ClearSequenceProgress() { ResetSequenceProgress(S_None); }
- void ResetSequenceProgress(Sequence NewSeq);
- 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; }
- };
- struct BottomUpPtrState : PtrState {
- BottomUpPtrState() = default;
- /// (Re-)Initialize this bottom up pointer returning true if we detected a
- /// pointer with nested releases.
- bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);
- /// Return true if this set of releases can be paired with a release. Modifies
- /// state appropriately to reflect that the matching occurred if it is
- /// successful.
- ///
- /// It is assumed that one has already checked that the RCIdentity of the
- /// retain and the RCIdentity of this ptr state are the same.
- bool MatchWithRetain();
- void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,
- ProvenanceAnalysis &PA, ARCInstKind Class);
- bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
- ProvenanceAnalysis &PA, ARCInstKind Class);
- };
- struct TopDownPtrState : PtrState {
- TopDownPtrState() = default;
- /// (Re-)Initialize this bottom up pointer returning true if we detected a
- /// pointer with nested releases.
- bool InitTopDown(ARCInstKind Kind, Instruction *I);
- /// Return true if this set of retains can be paired with the given
- /// release. Modifies state appropriately to reflect that the matching
- /// occurred.
- bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);
- void HandlePotentialUse(Instruction *Inst, const Value *Ptr,
- ProvenanceAnalysis &PA, ARCInstKind Class);
- bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,
- ProvenanceAnalysis &PA, ARCInstKind Class,
- const BundledRetainClaimRVs &BundledRVs);
- };
- } // end namespace objcarc
- } // end namespace llvm
- #endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H
|