brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 5cc4212 Raw
213 lines · c
1//===- PtrState.h - ARC State for a Ptr -------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9//  This file contains declarations for the ARC state associated with a ptr. It10//  is only used by the ARC Sequence Dataflow computation. By separating this11//  from the actual dataflow, it is easier to consider the mechanics of the ARC12//  optimization separate from the actual predicates being used.13//14//===----------------------------------------------------------------------===//15 16#ifndef LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H17#define LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H18 19#include "llvm/ADT/SmallPtrSet.h"20#include "llvm/Analysis/ObjCARCInstKind.h"21#include "llvm/Support/Compiler.h"22 23namespace llvm {24 25class BasicBlock;26class Instruction;27class MDNode;28class raw_ostream;29class Value;30 31namespace objcarc {32 33class ARCMDKindCache;34class BundledRetainClaimRVs;35class ProvenanceAnalysis;36 37/// \enum Sequence38///39/// A sequence of states that a pointer may go through in which an40/// objc_retain and objc_release are actually needed.41enum Sequence {42  S_None,43  S_Retain,        ///< objc_retain(x).44  S_CanRelease,    ///< foo(x) -- x could possibly see a ref count decrement.45  S_Use,           ///< any use of x.46  S_Stop,          ///< code motion is stopped.47  S_MovableRelease ///< objc_release(x), !clang.imprecise_release.48};49 50[[maybe_unused]] raw_ostream &operator<<(raw_ostream &OS, const Sequence S);51 52/// 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.68  bool KnownSafe = false;69 70  /// True of the objc_release calls are all marked with the "tail" keyword.71  bool IsTailCallRelease = false;72 73  /// If the Calls are objc_release calls and they all have a74  /// clang.imprecise_release tag, this is the metadata tag.75  MDNode *ReleaseMetadata = nullptr;76 77  /// For a top-down sequence, the set of objc_retains or78  /// objc_retainBlocks. For bottom-up, the set of objc_releases.79  SmallPtrSet<Instruction *, 2> Calls;80 81  /// The set of optimal insert positions for moving calls in the opposite82  /// sequence.83  SmallPtrSet<Instruction *, 2> ReverseInsertPts;84 85  /// If this is true, we cannot perform code motion but can still remove86  /// retain/release pairs.87  bool CFGHazardAfflicted = false;88 89  RRInfo() = default;90 91  void clear();92 93  /// Conservatively merge the two RRInfo. Returns true if a partial merge has94  /// occurred, false otherwise.95  bool Merge(const RRInfo &Other);96};97 98/// 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.103  bool KnownPositiveRefCount = false;104 105  /// 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.107  bool Partial = false;108 109  /// The current position in the sequence.110  unsigned char Seq : 8;111 112  /// Unidirectional information about the current sequence.113  RRInfo RRI;114 115  PtrState() : Seq(S_None) {}116 117public:118  bool IsKnownSafe() const { return RRI.KnownSafe; }119 120  void SetKnownSafe(const bool NewValue) { RRI.KnownSafe = NewValue; }121 122  bool IsTailCallRelease() const { return RRI.IsTailCallRelease; }123 124  void SetTailCallRelease(const bool NewValue) {125    RRI.IsTailCallRelease = NewValue;126  }127 128  bool IsTrackingImpreciseReleases() const {129    return RRI.ReleaseMetadata != nullptr;130  }131 132  const MDNode *GetReleaseMetadata() const { return RRI.ReleaseMetadata; }133 134  void SetReleaseMetadata(MDNode *NewValue) { RRI.ReleaseMetadata = NewValue; }135 136  bool IsCFGHazardAfflicted() const { return RRI.CFGHazardAfflicted; }137 138  void SetCFGHazardAfflicted(const bool NewValue) {139    RRI.CFGHazardAfflicted = NewValue;140  }141 142  void SetKnownPositiveRefCount();143  void ClearKnownPositiveRefCount();144 145  bool HasKnownPositiveRefCount() const { return KnownPositiveRefCount; }146 147  void SetSeq(Sequence NewSeq);148 149  Sequence GetSeq() const { return static_cast<Sequence>(Seq); }150 151  void ClearSequenceProgress() { ResetSequenceProgress(S_None); }152 153  void ResetSequenceProgress(Sequence NewSeq);154  void Merge(const PtrState &Other, bool TopDown);155 156  void InsertCall(Instruction *I) { RRI.Calls.insert(I); }157 158  void InsertReverseInsertPt(Instruction *I) { RRI.ReverseInsertPts.insert(I); }159 160  void ClearReverseInsertPts() { RRI.ReverseInsertPts.clear(); }161 162  bool HasReverseInsertPts() const { return !RRI.ReverseInsertPts.empty(); }163 164  const RRInfo &GetRRInfo() const { return RRI; }165};166 167struct BottomUpPtrState : PtrState {168  BottomUpPtrState() = default;169 170  /// (Re-)Initialize this bottom up pointer returning true if we detected a171  /// pointer with nested releases.172  bool InitBottomUp(ARCMDKindCache &Cache, Instruction *I);173 174  /// 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.180  bool MatchWithRetain();181 182  void HandlePotentialUse(BasicBlock *BB, Instruction *Inst, const Value *Ptr,183                          ProvenanceAnalysis &PA, ARCInstKind Class);184  bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,185                                    ProvenanceAnalysis &PA, ARCInstKind Class);186};187 188struct TopDownPtrState : PtrState {189  TopDownPtrState() = default;190 191  /// (Re-)Initialize this bottom up pointer returning true if we detected a192  /// pointer with nested releases.193  bool InitTopDown(ARCInstKind Kind, Instruction *I);194 195  /// Return true if this set of retains can be paired with the given196  /// release. Modifies state appropriately to reflect that the matching197  /// occurred.198  bool MatchWithRelease(ARCMDKindCache &Cache, Instruction *Release);199 200  void HandlePotentialUse(Instruction *Inst, const Value *Ptr,201                          ProvenanceAnalysis &PA, ARCInstKind Class);202 203  bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,204                                    ProvenanceAnalysis &PA, ARCInstKind Class,205                                    const BundledRetainClaimRVs &BundledRVs);206};207 208} // end namespace objcarc209 210} // end namespace llvm211 212#endif // LLVM_LIB_TRANSFORMS_OBJCARC_PTRSTATE_H213