Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/ObjCARC/PtrState.h
35269 views
//===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains declarations for the ARC state associated with a ptr. It9// is only used by the ARC Sequence Dataflow computation. By separating this10// from the actual dataflow, it is easier to consider the mechanics of the ARC11// optimization separate from the actual predicates being used.12//13//===----------------------------------------------------------------------===//1415#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H16#define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H1718#include "llvm/ADT/SmallPtrSet.h"19#include "llvm/Analysis/ObjCARCInstKind.h"20#include "llvm/Support/Compiler.h"2122namespace llvm {2324class BasicBlock;25class Instruction;26class MDNode;27class raw_ostream;28class Value;2930namespace objcarc {3132class ARCMDKindCache;33class BundledRetainClaimRVs;34class ProvenanceAnalysis;3536/// \enum Sequence37///38/// A sequence of states that a pointer may go through in which an39/// objc_retain and objc_release are actually needed.40enum Sequence {41S_None,42S_Retain, ///< objc_retain(x).43S_CanRelease, ///< foo(x) -- x could possibly see a ref count decrement.44S_Use, ///< any use of x.45S_Stop, ///< code motion is stopped.46S_MovableRelease ///< objc_release(x), !clang.imprecise_release.47};4849raw_ostream &operator<<(raw_ostream &OS,50const Sequence S) LLVM_ATTRIBUTE_UNUSED;5152/// Unidirectional information about either a53/// retain-decrement-use-release sequence or release-use-decrement-retain54/// reverse sequence.55struct RRInfo {56/// After an objc_retain, the reference count of the referenced57/// object is known to be positive. Similarly, before an objc_release, the58/// reference count of the referenced object is known to be positive. If59/// there are retain-release pairs in code regions where the retain count60/// is known to be positive, they can be eliminated, regardless of any side61/// effects between them.62///63/// Also, a retain+release pair nested within another retain+release64/// pair all on the known same pointer value can be eliminated, regardless65/// of any intervening side effects.66///67/// KnownSafe is true when either of these conditions is satisfied.68bool KnownSafe = false;6970/// True of the objc_release calls are all marked with the "tail" keyword.71bool IsTailCallRelease = false;7273/// If the Calls are objc_release calls and they all have a74/// clang.imprecise_release tag, this is the metadata tag.75MDNode *ReleaseMetadata = nullptr;7677/// For a top-down sequence, the set of objc_retains or78/// objc_retainBlocks. For bottom-up, the set of objc_releases.79SmallPtrSet<Instruction *, 2> Calls;8081/// The set of optimal insert positions for moving calls in the opposite82/// sequence.83SmallPtrSet<Instruction *, 2> ReverseInsertPts;8485/// If this is true, we cannot perform code motion but can still remove86/// retain/release pairs.87bool CFGHazardAfflicted = false;8889RRInfo() = default;9091void clear();9293/// Conservatively merge the two RRInfo. Returns true if a partial merge has94/// occurred, false otherwise.95bool Merge(const RRInfo &Other);96};9798/// This class summarizes several per-pointer runtime properties which99/// are propagated through the flow graph.100class PtrState {101protected:102/// True if the reference count is known to be incremented.103bool KnownPositiveRefCount = false;104105/// True if we've seen an opportunity for partial RR elimination, such as106/// pushing calls into a CFG triangle or into one side of a CFG diamond.107bool Partial = false;108109/// The current position in the sequence.110unsigned char Seq : 8;111112/// Unidirectional information about the current sequence.113RRInfo RRI;114115PtrState() : Seq(S_None) {}116117public:118bool IsKnownSafe() const { return RRI.KnownSafe; }119120void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }121122bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }123124void SetTailCallRelease(const bool NewValue) {125RRI.IsTailCallRelease = NewValue;126}127128bool IsTrackingImpreciseReleases() const {129return RRI.ReleaseMetadata != nullptr;130}131132const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }133134void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }135136bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }137138void SetCFGHazardAfflicted(const bool NewValue) {139RRI.CFGHazardAfflicted = NewValue;140}141142void SetKnownPositiveRefCount();143void ClearKnownPositiveRefCount();144145bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }146147void SetSeq(Sequence NewSeq);148149Sequence GetSeq() const { return static_cast<Sequence>(Seq); }150151void ClearSequenceProgress() { ResetSequenceProgress(S_None); }152153void ResetSequenceProgress(Sequence NewSeq);154void Merge(const PtrState &Other, bool TopDown);155156void InsertCall(Instruction *I) { RRI.Calls.insert(I); }157158void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }159160void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }161162bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }163164const RRInfo &GetRRInfo() const { return RRI; }165};166167struct BottomUpPtrState : PtrState {168BottomUpPtrState() = default;169170/// (Re-)Initialize this bottom up pointer returning true if we detected a171/// pointer with nested releases.172bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);173174/// Return true if this set of releases can be paired with a release. Modifies175/// state appropriately to reflect that the matching occurred if it is176/// successful.177///178/// It is assumed that one has already checked that the RCIdentity of the179/// retain and the RCIdentity of this ptr state are the same.180bool MatchWithRetain();181182void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,183ProvenanceAnalysis &PA, ARCInstKind Class);184bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,185ProvenanceAnalysis &PA, ARCInstKind Class);186};187188struct TopDownPtrState : PtrState {189TopDownPtrState() = default;190191/// (Re-)Initialize this bottom up pointer returning true if we detected a192/// pointer with nested releases.193bool InitTopDown(ARCInstKind Kind, Instruction *I);194195/// Return true if this set of retains can be paired with the given196/// release. Modifies state appropriately to reflect that the matching197/// occurred.198bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);199200void HandlePotentialUse(Instruction *Inst, const Value *Ptr,201ProvenanceAnalysis &PA, ARCInstKind Class);202203bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,204ProvenanceAnalysis &PA, ARCInstKind Class,205const BundledRetainClaimRVs &BundledRVs);206};207208} // end namespace objcarc209210} // end namespace llvm211212#endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H213214215