[PM/AA] Run clang-format over the ObjCARC Alias Analysis code to
[oota-llvm.git] / lib / Transforms / ObjCARC / PtrState.cpp
index 9a82f36c5c46831ab651720b5c09830f60d75675..ae20e7e6d347c3112ee8b05c9fce47928a6c6636 100644 (file)
@@ -7,14 +7,21 @@
 //
 //===----------------------------------------------------------------------===//
 
-#define DEBUG_TYPE "objc-arc-ptr-state"
-#include "llvm/Support/Debug.h"
 #include "PtrState.h"
+#include "DependencyAnalysis.h"
 #include "ObjCARC.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
 using namespace llvm::objcarc;
 
+#define DEBUG_TYPE "objc-arc-ptr-state"
+
+//===----------------------------------------------------------------------===//
+//                                  Utility
+//===----------------------------------------------------------------------===//
+
 raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
   switch (S) {
   case S_None:
@@ -35,6 +42,10 @@ raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS, const Sequence S) {
   llvm_unreachable("Unknown sequence type.");
 }
 
+//===----------------------------------------------------------------------===//
+//                                  Sequence
+//===----------------------------------------------------------------------===//
+
 static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
   // The easy cases.
   if (A == B)
@@ -64,6 +75,10 @@ static Sequence MergeSeqs(Sequence A, Sequence B, bool TopDown) {
   return S_None;
 }
 
+//===----------------------------------------------------------------------===//
+//                                   RRInfo
+//===----------------------------------------------------------------------===//
+
 void RRInfo::clear() {
   KnownSafe = false;
   IsTailCallRelease = false;
@@ -94,23 +109,27 @@ bool RRInfo::Merge(const RRInfo &Other) {
   return Partial;
 }
 
+//===----------------------------------------------------------------------===//
+//                                  PtrState
+//===----------------------------------------------------------------------===//
+
 void PtrState::SetKnownPositiveRefCount() {
-  DEBUG(dbgs() << "Setting Known Positive.\n");
+  DEBUG(dbgs() << "        Setting Known Positive.\n");
   KnownPositiveRefCount = true;
 }
 
 void PtrState::ClearKnownPositiveRefCount() {
-  DEBUG(dbgs() << "Clearing Known Positive.\n");
+  DEBUG(dbgs() << "        Clearing Known Positive.\n");
   KnownPositiveRefCount = false;
 }
 
 void PtrState::SetSeq(Sequence NewSeq) {
-  DEBUG(dbgs() << "Old: " << Seq << "; New: " << NewSeq << "\n");
+  DEBUG(dbgs() << "            Old: " << GetSeq() << "; New: " << NewSeq << "\n");
   Seq = NewSeq;
 }
 
 void PtrState::ResetSequenceProgress(Sequence NewSeq) {
-  DEBUG(dbgs() << "Resetting sequence progress.\n");
+  DEBUG(dbgs() << "        Resetting sequence progress.\n");
   SetSeq(NewSeq);
   Partial = false;
   RRI.clear();
@@ -139,6 +158,10 @@ void PtrState::Merge(const PtrState &Other, bool TopDown) {
   }
 }
 
+//===----------------------------------------------------------------------===//
+//                              BottomUpPtrState
+//===----------------------------------------------------------------------===//
+
 bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
   // If we see two releases in a row on the same pointer. If so, make
   // a note, and we'll cicle back to revisit it after we've
@@ -149,11 +172,12 @@ bool BottomUpPtrState::InitBottomUp(ARCMDKindCache &Cache, Instruction *I) {
   // simple and avoids adding overhead for the non-nested case.
   bool NestingDetected = false;
   if (GetSeq() == S_Release || GetSeq() == S_MovableRelease) {
-    DEBUG(dbgs() << "Found nested releases (i.e. a release pair)\n");
+    DEBUG(dbgs() << "        Found nested releases (i.e. a release pair)\n");
     NestingDetected = true;
   }
 
-  MDNode *ReleaseMetadata = I->getMetadata(Cache.ImpreciseReleaseMDKind);
+  MDNode *ReleaseMetadata =
+      I->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
   Sequence NewSeq = ReleaseMetadata ? S_MovableRelease : S_Release;
   ResetSequenceProgress(NewSeq);
   SetReleaseMetadata(ReleaseMetadata);
@@ -185,8 +209,90 @@ bool BottomUpPtrState::MatchWithRetain() {
   case S_Retain:
     llvm_unreachable("bottom-up pointer in retain state!");
   }
+  llvm_unreachable("Sequence unknown enum value");
 }
 
+bool BottomUpPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
+                                                    const Value *Ptr,
+                                                    ProvenanceAnalysis &PA,
+                                                    ARCInstKind Class) {
+  Sequence S = GetSeq();
+
+  // Check for possible releases.
+  if (!CanAlterRefCount(Inst, Ptr, PA, Class))
+    return false;
+
+  DEBUG(dbgs() << "            CanAlterRefCount: Seq: " << S << "; " << *Ptr
+               << "\n");
+  switch (S) {
+  case S_Use:
+    SetSeq(S_CanRelease);
+    return true;
+  case S_CanRelease:
+  case S_Release:
+  case S_MovableRelease:
+  case S_Stop:
+  case S_None:
+    return false;
+  case S_Retain:
+    llvm_unreachable("bottom-up pointer in retain state!");
+  }
+  llvm_unreachable("Sequence unknown enum value");
+}
+
+void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,
+                                          const Value *Ptr,
+                                          ProvenanceAnalysis &PA,
+                                          ARCInstKind Class) {
+  // Check for possible direct uses.
+  switch (GetSeq()) {
+  case S_Release:
+  case S_MovableRelease:
+    if (CanUse(Inst, Ptr, PA, Class)) {
+      DEBUG(dbgs() << "            CanUse: Seq: " << GetSeq() << "; " << *Ptr
+                   << "\n");
+      assert(!HasReverseInsertPts());
+      // If this is an invoke instruction, we're scanning it as part of
+      // one of its successor blocks, since we can't insert code after it
+      // in its own block, and we don't want to split critical edges.
+      if (isa<InvokeInst>(Inst))
+        InsertReverseInsertPt(BB->getFirstInsertionPt());
+      else
+        InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
+      SetSeq(S_Use);
+    } else if (Seq == S_Release && IsUser(Class)) {
+      DEBUG(dbgs() << "            PreciseReleaseUse: Seq: " << GetSeq() << "; "
+                   << *Ptr << "\n");
+      // Non-movable releases depend on any possible objc pointer use.
+      SetSeq(S_Stop);
+      assert(!HasReverseInsertPts());
+      // As above; handle invoke specially.
+      if (isa<InvokeInst>(Inst))
+        InsertReverseInsertPt(BB->getFirstInsertionPt());
+      else
+        InsertReverseInsertPt(std::next(BasicBlock::iterator(Inst)));
+    }
+    break;
+  case S_Stop:
+    if (CanUse(Inst, Ptr, PA, Class)) {
+      DEBUG(dbgs() << "            PreciseStopUse: Seq: " << GetSeq() << "; "
+                   << *Ptr << "\n");
+      SetSeq(S_Use);
+    }
+    break;
+  case S_CanRelease:
+  case S_Use:
+  case S_None:
+    break;
+  case S_Retain:
+    llvm_unreachable("bottom-up pointer in retain state!");
+  }
+}
+
+//===----------------------------------------------------------------------===//
+//                              TopDownPtrState
+//===----------------------------------------------------------------------===//
+
 bool TopDownPtrState::InitTopDown(ARCInstKind Kind, Instruction *I) {
   bool NestingDetected = false;
   // Don't do retain+release tracking for ARCInstKind::RetainRV, because
@@ -218,7 +324,8 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
 
   Sequence OldSeq = GetSeq();
 
-  MDNode *ReleaseMetadata = Release->getMetadata(Cache.ImpreciseReleaseMDKind);
+  MDNode *ReleaseMetadata =
+      Release->getMetadata(Cache.get(ARCMDKindID::ImpreciseRelease));
 
   switch (OldSeq) {
   case S_Retain:
@@ -237,4 +344,61 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,
   case S_MovableRelease:
     llvm_unreachable("top-down pointer in bottom up state!");
   }
+  llvm_unreachable("Sequence unknown enum value");
+}
+
+bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,
+                                                   const Value *Ptr,
+                                                   ProvenanceAnalysis &PA,
+                                                   ARCInstKind Class) {
+  // Check for possible releases.
+  if (!CanAlterRefCount(Inst, Ptr, PA, Class))
+    return false;
+
+  DEBUG(dbgs() << "            CanAlterRefCount: Seq: " << GetSeq() << "; " << *Ptr
+               << "\n");
+  ClearKnownPositiveRefCount();
+  switch (GetSeq()) {
+  case S_Retain:
+    SetSeq(S_CanRelease);
+    assert(!HasReverseInsertPts());
+    InsertReverseInsertPt(Inst);
+
+    // One call can't cause a transition from S_Retain to S_CanRelease
+    // and S_CanRelease to S_Use. If we've made the first transition,
+    // we're done.
+    return true;
+  case S_Use:
+  case S_CanRelease:
+  case S_None:
+    return false;
+  case S_Stop:
+  case S_Release:
+  case S_MovableRelease:
+    llvm_unreachable("top-down pointer in release state!");
+  }
+  llvm_unreachable("covered switch is not covered!?");
+}
+
+void TopDownPtrState::HandlePotentialUse(Instruction *Inst, const Value *Ptr,
+                                         ProvenanceAnalysis &PA,
+                                         ARCInstKind Class) {
+  // Check for possible direct uses.
+  switch (GetSeq()) {
+  case S_CanRelease:
+    if (!CanUse(Inst, Ptr, PA, Class))
+      return;
+    DEBUG(dbgs() << "             CanUse: Seq: " << GetSeq() << "; " << *Ptr
+                 << "\n");
+    SetSeq(S_Use);
+    return;
+  case S_Retain:
+  case S_Use:
+  case S_None:
+    return;
+  case S_Stop:
+  case S_Release:
+  case S_MovableRelease:
+    llvm_unreachable("top-down pointer in release state!");
+  }
 }