[llvm] Think in terms of blocks for ARC (PR #130860)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 14 06:33:34 PDT 2025


https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/130860

>From fe3610f44aa72c79447c4e2c6164d0f3aeaf98d3 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Mon, 10 Mar 2025 14:24:09 -0400
Subject: [PATCH] Think in terms of blocks

Handle critical edges for ObjCARC
---
 llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp   |  102 +-
 llvm/test/Transforms/ObjCARC/allocas.ll       |  403 ++-
 llvm/test/Transforms/ObjCARC/basic.ll         | 2234 +++++++++++------
 .../ObjCARC/clang-arc-use-barrier.ll          |   27 +-
 llvm/test/Transforms/ObjCARC/code-motion.ll   |  106 +-
 .../Transforms/ObjCARC/funclet-catchpad.ll    |   29 +-
 llvm/test/Transforms/ObjCARC/intrinsic-use.ll |  106 +-
 llvm/test/Transforms/ObjCARC/invoke.ll        |  211 +-
 llvm/test/Transforms/ObjCARC/nested.ll        |  658 ++++-
 .../test/Transforms/ObjCARC/split-backedge.ll |   42 +-
 10 files changed, 2854 insertions(+), 1064 deletions(-)

diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index 9d7f5e64f9868..60bd238476f03 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -138,12 +138,6 @@ static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
 // calls followed by objc_autoreleasePoolPop calls (perhaps in ObjC++ code
 // after inlining) can be turned into plain release calls.
 
-// TODO: Critical-edge splitting. If the optimial insertion point is
-// a critical edge, the current algorithm has to fail, because it doesn't
-// know how to split edges. It should be possible to make the optimizer
-// think in terms of edges, rather than blocks, and then split critical
-// edges on demand.
-
 // TODO: OptimizeSequences could generalized to be Interprocedural.
 
 // TODO: Recognize that a bunch of other objc runtime calls have
@@ -599,6 +593,7 @@ class ObjCARCOpt {
     void init(Function &F);
     bool run(Function &F, AAResults &AA);
     bool hasCFGChanged() const { return CFGChanged; }
+    BasicBlock *SplitCriticalEdge(BasicBlock *Pred, BasicBlock *Succ);
 };
 } // end anonymous namespace
 
@@ -1765,8 +1760,50 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
                            Module *M) {
   LLVM_DEBUG(dbgs() << "== ObjCARCOpt::MoveCalls ==\n");
 
-  // Insert the new retain and release calls.
+  // First, handle critical edges for retain insertion points
+  SmallVector<Instruction *, 4> NewRetainInsertPts;
+  for (Instruction *InsertPt : RetainsToMove.ReverseInsertPts) {
+    BasicBlock *BB = InsertPt->getParent();
+    BasicBlock *Pred = BB->getUniquePredecessor();
+
+    // If this is a critical edge, split it
+    if (!Pred && BB->hasNPredecessors(1)) {
+      for (BasicBlock *PredBB : predecessors(BB)) {
+        if (PredBB->getTerminator()->getNumSuccessors() > 1) {
+          if (BasicBlock *NewBB = SplitCriticalEdge(PredBB, BB)) {
+            // Add the new block as an insertion point
+            NewRetainInsertPts.push_back(NewBB->getTerminator());
+          }
+        }
+      }
+    } else {
+      NewRetainInsertPts.push_back(InsertPt);
+    }
+  }
+
+  // Then handle critical edges for release insertion points
+  SmallVector<Instruction *, 4> NewReleaseInsertPts;
   for (Instruction *InsertPt : ReleasesToMove.ReverseInsertPts) {
+    BasicBlock *BB = InsertPt->getParent();
+    BasicBlock *Pred = BB->getUniquePredecessor();
+
+    // If this is a critical edge, split it
+    if (!Pred && BB->hasNPredecessors(1)) {
+      for (BasicBlock *PredBB : predecessors(BB)) {
+        if (PredBB->getTerminator()->getNumSuccessors() > 1) {
+          if (BasicBlock *NewBB = SplitCriticalEdge(PredBB, BB)) {
+            // Add the new block as an insertion point
+            NewReleaseInsertPts.push_back(NewBB->getTerminator());
+          }
+        }
+      }
+    } else {
+      NewReleaseInsertPts.push_back(InsertPt);
+    }
+  }
+
+  // Now insert the new retain calls at the split points
+  for (Instruction *InsertPt : NewRetainInsertPts) {
     Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain);
     SmallVector<OperandBundleDef, 1> BundleList;
     addOpBundleForFunclet(InsertPt->getParent(), BundleList);
@@ -1780,7 +1817,9 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove,
                          "At insertion point: "
                       << *InsertPt << "\n");
   }
-  for (Instruction *InsertPt : RetainsToMove.ReverseInsertPts) {
+
+  // And insert the new release calls at the split points
+  for (Instruction *InsertPt : NewReleaseInsertPts) {
     Function *Decl = EP.get(ARCRuntimeEntryPointKind::Release);
     SmallVector<OperandBundleDef, 1> BundleList;
     addOpBundleForFunclet(InsertPt->getParent(), BundleList);
@@ -2488,6 +2527,53 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
   return Changed;
 }
 
+/// Split critical edges where we need to insert retain/release calls
+BasicBlock *ObjCARCOpt::SplitCriticalEdge(BasicBlock *Pred, BasicBlock *Succ) {
+  // Don't split if either block is a landing pad - we want to maintain
+  // the property that landing pads have exactly one predecessor
+  if (Succ->isLandingPad() || isa<InvokeInst>(Pred->getTerminator()))
+    return nullptr;
+
+  // We need both multiple successors in predecessor and
+  // multiple predecessors in successor
+  if (Pred->getTerminator()->getNumSuccessors() <= 1 ||
+      Succ->getUniquePredecessor())
+    return nullptr;
+
+  // Create a new basic block for the split edge
+  BasicBlock *NewBB = BasicBlock::Create(
+      Pred->getContext(), Pred->getName() + "." + Succ->getName() + ".arc",
+      Pred->getParent());
+
+  // Update the terminator of Pred to branch to NewBB instead of Succ
+  BranchInst *Term = cast<BranchInst>(Pred->getTerminator());
+  for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
+    if (Term->getSuccessor(i) == Succ) {
+      Term->setSuccessor(i, NewBB);
+      break;
+    }
+  }
+
+  // Create an unconditional branch from NewBB to Succ
+  BranchInst::Create(Succ, NewBB);
+
+  // Update PHI nodes in Succ
+  for (PHINode &PHI : Succ->phis()) {
+    Value *V = PHI.getIncomingValueForBlock(Pred);
+    PHI.setIncomingBlock(PHI.getBasicBlockIndex(Pred), NewBB);
+    PHI.addIncoming(V, Pred);
+  }
+
+  // Update any funclet bundles
+  if (!BlockEHColors.empty()) {
+    const ColorVector &CV = BlockEHColors.find(Pred)->second;
+    BlockEHColors[NewBB] = CV;
+  }
+
+  CFGChanged = true;
+  return NewBB;
+}
+
 /// @}
 ///
 
diff --git a/llvm/test/Transforms/ObjCARC/allocas.ll b/llvm/test/Transforms/ObjCARC/allocas.ll
index 6fe2edf3e2dd4..03f428e96683e 100644
--- a/llvm/test/Transforms/ObjCARC/allocas.ll
+++ b/llvm/test/Transforms/ObjCARC/allocas.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
 
 declare ptr @llvm.objc.retain(ptr)
@@ -31,7 +32,7 @@ declare ptr @objc_msgSend(ptr, ptr, ...)
 ; In the presence of allocas, unconditionally remove retain/release pairs only
 ; if they are known safe in both directions. This prevents matching up an inner
 ; retain with the boundary guarding release in the following situation:
-; 
+;
 ; %A = alloca
 ; retain(%x)
 ; retain(%x) <--- Inner Retain
@@ -43,14 +44,21 @@ declare ptr @objc_msgSend(ptr, ptr, ...)
 ;
 ; rdar://13750319
 
-; CHECK: define void @test1a(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1a(ptr %x) {
+; CHECK-LABEL: define void @test1a(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0:![0-9]+]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr
   tail call ptr @llvm.objc.retain(ptr %x)
@@ -64,14 +72,21 @@ entry:
   ret void
 }
 
-; CHECK: define void @test1b(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1b(ptr %x) {
+; CHECK-LABEL: define void @test1b(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr
   tail call ptr @llvm.objc.retain(ptr %x)
@@ -86,14 +101,22 @@ entry:
 }
 
 
-; CHECK: define void @test1c(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1c(ptr %x) {
+; CHECK-LABEL: define void @test1c(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, i32 3, align 8
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr ptr, ptr [[A]], i32 2
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[GEP]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[GEP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr, i32 3
   %gep = getelementptr ptr, ptr %A, i32 2
@@ -109,14 +132,29 @@ entry:
 }
 
 
-; CHECK: define void @test1d(ptr %x, i1 %arg)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1d(ptr %x, i1 %arg) {
+; CHECK-LABEL: define void @test1d(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[ARG]], label %[[USE_ALLOCAA:.*]], label %[[USE_ALLOCAB:.*]]
+; CHECK:       [[USE_ALLOCAA]]:
+; CHECK-NEXT:    [[ALLOCAA:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    br label %[[EXIT:.*]]
+; CHECK:       [[USE_ALLOCAB]]:
+; CHECK-NEXT:    [[ALLOCAB:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[A:%.*]] = phi ptr [ [[ALLOCAA]], %[[USE_ALLOCAA]] ], [ [[ALLOCAB]], %[[USE_ALLOCAB]] ]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %arg, label %use_allocaA, label %use_allocaB
 
@@ -141,14 +179,30 @@ exit:
   ret void
 }
 
-; CHECK: define void @test1e(ptr %x, i1 %arg)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1e(ptr %x, i1 %arg) {
+; CHECK-LABEL: define void @test1e(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[ARG]], label %[[USE_ALLOCAA:.*]], label %[[USE_ALLOCAB:.*]]
+; CHECK:       [[USE_ALLOCAA]]:
+; CHECK-NEXT:    [[ALLOCAA:%.*]] = alloca ptr, i32 4, align 8
+; CHECK-NEXT:    br label %[[EXIT:.*]]
+; CHECK:       [[USE_ALLOCAB]]:
+; CHECK-NEXT:    [[ALLOCAB:%.*]] = alloca ptr, i32 4, align 8
+; CHECK-NEXT:    br label %[[EXIT]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[A:%.*]] = phi ptr [ [[ALLOCAA]], %[[USE_ALLOCAA]] ], [ [[ALLOCAB]], %[[USE_ALLOCAB]] ]
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr ptr, ptr [[A]], i32 2
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[GEP]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[GEP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %arg, label %use_allocaA, label %use_allocaB
 
@@ -174,14 +228,23 @@ exit:
   ret void
 }
 
-; CHECK: define void @test1f(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test1f(ptr %x) {
+; CHECK-LABEL: define void @test1f(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[ALLOCAONE:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[ALLOCATWO:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[A:%.*]] = select i1 undef, ptr [[ALLOCAONE]], ptr [[ALLOCATWO]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %allocaOne = alloca ptr
   %allocaTwo = alloca ptr
@@ -201,14 +264,27 @@ entry:
 ; conservatively.
 
 
-; CHECK: define void @test2a(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test2a(ptr %x) {
+; CHECK-LABEL: define void @test2a(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    br label %[[BB1:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br label %[[BB2:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br label %[[BB3:.*]]
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr
   store ptr %x, ptr %A, align 8
@@ -231,14 +307,27 @@ bb3:
   ret void
 }
 
-; CHECK: define void @test2b(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test2b(ptr %x) {
+; CHECK-LABEL: define void @test2b(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    store ptr [[X]], ptr [[A]], align 8
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[A]], align 8
+; CHECK-NEXT:    br label %[[BB1:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br label %[[BB2:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br label %[[BB3:.*]]
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr
   store ptr %x, ptr %A, align 8
@@ -261,14 +350,29 @@ bb3:
   ret void
 }
 
-; CHECK: define void @test2c(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test2c(ptr %x) {
+; CHECK-LABEL: define void @test2c(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[A:%.*]] = alloca ptr, i32 3, align 8
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr ptr, ptr [[A]], i32 2
+; CHECK-NEXT:    store ptr [[X]], ptr [[GEP1]], align 8
+; CHECK-NEXT:    [[GEP2:%.*]] = getelementptr ptr, ptr [[A]], i32 2
+; CHECK-NEXT:    [[Y:%.*]] = load ptr, ptr [[GEP2]], align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[BB1:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    br label %[[BB2:.*]]
+; CHECK:       [[BB2]]:
+; CHECK-NEXT:    br label %[[BB3:.*]]
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %A = alloca ptr, i32 3
   %gep1 = getelementptr ptr, ptr %A, i32 2
@@ -293,14 +397,36 @@ bb3:
   ret void
 }
 
-; CHECK: define void @test2d(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %y)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: ret void
-; CHECK: }
 define void @test2d(ptr %x) {
+; CHECK-LABEL: define void @test2d(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[BB1:.*]]
+; CHECK:       [[BB1]]:
+; CHECK-NEXT:    [[ABB1:%.*]] = alloca ptr, i32 3, align 8
+; CHECK-NEXT:    [[GEPBB11:%.*]] = getelementptr ptr, ptr [[ABB1]], i32 2
+; CHECK-NEXT:    store ptr [[X]], ptr [[GEPBB11]], align 8
+; CHECK-NEXT:    [[GEPBB12:%.*]] = getelementptr ptr, ptr [[ABB1]], i32 2
+; CHECK-NEXT:    [[YBB1:%.*]] = load ptr, ptr [[GEPBB12]], align 8
+; CHECK-NEXT:    br label %[[BB3:.*]]
+; CHECK:       [[BB2:.*]]:
+; CHECK-NEXT:    [[ABB2:%.*]] = alloca ptr, i32 4, align 8
+; CHECK-NEXT:    [[GEPBB21:%.*]] = getelementptr ptr, ptr [[ABB2]], i32 2
+; CHECK-NEXT:    store ptr [[X]], ptr [[GEPBB21]], align 8
+; CHECK-NEXT:    [[GEPBB22:%.*]] = getelementptr ptr, ptr [[ABB2]], i32 2
+; CHECK-NEXT:    [[YBB2:%.*]] = load ptr, ptr [[GEPBB22]], align 8
+; CHECK-NEXT:    br label %[[BB3]]
+; CHECK:       [[BB3]]:
+; CHECK-NEXT:    [[A:%.*]] = phi ptr [ [[ABB1]], %[[BB1]] ], [ [[ABB2]], %[[BB2]] ]
+; CHECK-NEXT:    [[Y:%.*]] = phi ptr [ [[YBB1]], %[[BB1]] ], [ [[YBB2]], %[[BB2]] ]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_alloca(ptr [[A]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   tail call ptr @llvm.objc.retain(ptr %x)
   br label %bb1
@@ -338,30 +464,52 @@ bb3:
 ;
 ; rdar://13949644
 
-; CHECK: define void @test3a() {
-; CHECK: entry:
-; CHECK:   @llvm.objc.retainAutoreleasedReturnValue
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK: arraydestroy.body:
-; CHECK:   @llvm.objc.release
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.done:
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.body1:
-; CHECK:   @llvm.objc.release
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.done1:
-; CHECK: @llvm.objc.release
-; CHECK: ret void
-; CHECK: }
 define void @test3a() {
+; CHECK-LABEL: define void @test3a() {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[KEYS:%.*]] = alloca [2 x ptr], align 16
+; CHECK-NEXT:    [[OBJS:%.*]] = alloca [2 x ptr], align 16
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL1]], ptr [[OBJS]], align 8
+; CHECK-NEXT:    [[OBJS_ELT:%.*]] = getelementptr inbounds [2 x ptr], ptr [[OBJS]], i64 0, i64 1
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL1]], ptr [[OBJS_ELT]], align 8
+; CHECK-NEXT:    [[CALL2:%.*]] = call ptr @returner1()
+; CHECK-NEXT:    [[CALL3:%.*]] = call ptr @returner2()
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL2]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL2]], ptr [[KEYS]], align 8
+; CHECK-NEXT:    [[KEYS_ELT:%.*]] = getelementptr inbounds [2 x ptr], ptr [[KEYS]], i64 0, i64 1
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL3]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL3]], ptr [[KEYS_ELT]], align 8
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr [[OBJS]], i64 0, i64 2
+; CHECK-NEXT:    br label %[[ARRAYDESTROY_BODY:.*]]
+; CHECK:       [[ARRAYDESTROY_BODY]]:
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[GEP]], %[[ENTRY]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], %[[ARRAYDESTROY_BODY]] ]
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+; CHECK-NEXT:    [[DESTROY_TMP:%.*]] = load ptr, ptr [[ARRAYDESTROY_ELEMENT]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DESTROY_TMP]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[ARRAYDESTROY_CMP:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[OBJS]]
+; CHECK-NEXT:    br i1 [[ARRAYDESTROY_CMP]], label %[[ARRAYDESTROY_DONE:.*]], label %[[ARRAYDESTROY_BODY]]
+; CHECK:       [[ARRAYDESTROY_DONE]]:
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[KEYS]], i64 0, i64 2
+; CHECK-NEXT:    br label %[[ARRAYDESTROY_BODY1:.*]]
+; CHECK:       [[ARRAYDESTROY_BODY1]]:
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENTPAST1:%.*]] = phi ptr [ [[GEP1]], %[[ARRAYDESTROY_DONE]] ], [ [[ARRAYDESTROY_ELEMENT1:%.*]], %[[ARRAYDESTROY_BODY1]] ]
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENT1]] = getelementptr inbounds ptr, ptr [[ARRAYDESTROY_ELEMENTPAST1]], i64 -1
+; CHECK-NEXT:    [[DESTROY_TMP1:%.*]] = load ptr, ptr [[ARRAYDESTROY_ELEMENT1]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DESTROY_TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[ARRAYDESTROY_CMP1:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT1]], [[KEYS]]
+; CHECK-NEXT:    br i1 [[ARRAYDESTROY_CMP1]], label %[[ARRAYDESTROY_DONE1:.*]], label %[[ARRAYDESTROY_BODY1]]
+; CHECK:       [[ARRAYDESTROY_DONE1]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %keys = alloca [2 x ptr], align 16
   %objs = alloca [2 x ptr], align 16
-  
+
   %call1 = call ptr @returner()
   %tmp0 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1)
 
@@ -377,8 +525,8 @@ entry:
   store ptr %call2, ptr %keys, align 8
   %keys.elt = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 1
   tail call ptr @llvm.objc.retain(ptr %call3)
-  store ptr %call3, ptr %keys.elt  
-  
+  store ptr %call3, ptr %keys.elt
+
   %gep = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 2
   br label %arraydestroy.body
 
@@ -412,30 +560,52 @@ arraydestroy.done1:
 ;
 ; rdar://13949644
 
-; CHECK: define void @test3b() {
-; CHECK: entry:
-; CHECK:   @llvm.objc.retainAutoreleasedReturnValue
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.retain
-; CHECK: arraydestroy.body:
-; CHECK:   @llvm.objc.release
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.done:
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.body1:
-; CHECK:   @llvm.objc.release
-; CHECK-NOT: @llvm.objc.release
-; CHECK: arraydestroy.done1:
-; CHECK: @llvm.objc.release
-; CHECK: ret void
-; CHECK: }
 define void @test3b() {
+; CHECK-LABEL: define void @test3b() {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[KEYS:%.*]] = alloca [2 x ptr], align 16
+; CHECK-NEXT:    [[OBJS:%.*]] = alloca [2 x ptr], align 16
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL1]], ptr [[OBJS]], align 8
+; CHECK-NEXT:    [[OBJS_ELT:%.*]] = getelementptr inbounds [2 x ptr], ptr [[OBJS]], i64 0, i64 1
+; CHECK-NEXT:    store ptr [[CALL1]], ptr [[OBJS_ELT]], align 8
+; CHECK-NEXT:    [[CALL2:%.*]] = call ptr @returner1()
+; CHECK-NEXT:    [[CALL3:%.*]] = call ptr @returner2()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL2]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL2]], ptr [[KEYS]], align 8
+; CHECK-NEXT:    [[KEYS_ELT:%.*]] = getelementptr inbounds [2 x ptr], ptr [[KEYS]], i64 0, i64 1
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL3]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[CALL3]], ptr [[KEYS_ELT]], align 8
+; CHECK-NEXT:    [[GEP:%.*]] = getelementptr inbounds [2 x ptr], ptr [[OBJS]], i64 0, i64 2
+; CHECK-NEXT:    br label %[[ARRAYDESTROY_BODY:.*]]
+; CHECK:       [[ARRAYDESTROY_BODY]]:
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENTPAST:%.*]] = phi ptr [ [[GEP]], %[[ENTRY]] ], [ [[ARRAYDESTROY_ELEMENT:%.*]], %[[ARRAYDESTROY_BODY]] ]
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENT]] = getelementptr inbounds ptr, ptr [[ARRAYDESTROY_ELEMENTPAST]], i64 -1
+; CHECK-NEXT:    [[DESTROY_TMP:%.*]] = load ptr, ptr [[ARRAYDESTROY_ELEMENT]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DESTROY_TMP]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[ARRAYDESTROY_CMP:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT]], [[OBJS]]
+; CHECK-NEXT:    br i1 [[ARRAYDESTROY_CMP]], label %[[ARRAYDESTROY_DONE:.*]], label %[[ARRAYDESTROY_BODY]]
+; CHECK:       [[ARRAYDESTROY_DONE]]:
+; CHECK-NEXT:    [[GEP1:%.*]] = getelementptr inbounds [2 x ptr], ptr [[KEYS]], i64 0, i64 2
+; CHECK-NEXT:    br label %[[ARRAYDESTROY_BODY1:.*]]
+; CHECK:       [[ARRAYDESTROY_BODY1]]:
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENTPAST1:%.*]] = phi ptr [ [[GEP1]], %[[ARRAYDESTROY_DONE]] ], [ [[ARRAYDESTROY_ELEMENT1:%.*]], %[[ARRAYDESTROY_BODY1]] ]
+; CHECK-NEXT:    [[ARRAYDESTROY_ELEMENT1]] = getelementptr inbounds ptr, ptr [[ARRAYDESTROY_ELEMENTPAST1]], i64 -1
+; CHECK-NEXT:    [[DESTROY_TMP1:%.*]] = load ptr, ptr [[ARRAYDESTROY_ELEMENT1]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DESTROY_TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[ARRAYDESTROY_CMP1:%.*]] = icmp eq ptr [[ARRAYDESTROY_ELEMENT1]], [[KEYS]]
+; CHECK-NEXT:    br i1 [[ARRAYDESTROY_CMP1]], label %[[ARRAYDESTROY_DONE1:.*]], label %[[ARRAYDESTROY_BODY1]]
+; CHECK:       [[ARRAYDESTROY_DONE1]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %keys = alloca [2 x ptr], align 16
   %objs = alloca [2 x ptr], align 16
-  
+
   %call1 = call ptr @returner()
   %tmp0 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1)
   %tmp1 = tail call ptr @llvm.objc.retain(ptr %call1)
@@ -452,8 +622,8 @@ entry:
   store ptr %call2, ptr %keys, align 8
   %keys.elt = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 1
   tail call ptr @llvm.objc.retain(ptr %call3)
-  store ptr %call3, ptr %keys.elt  
-  
+  store ptr %call3, ptr %keys.elt
+
   %gep = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 2
   br label %arraydestroy.body
 
@@ -486,3 +656,6 @@ arraydestroy.done1:
 !0 = !{}
 
 declare i32 @__gxx_personality_v0(...)
+;.
+; CHECK: [[META0]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/basic.ll b/llvm/test/Transforms/ObjCARC/basic.ll
index aa0c53b4f4851..e92ac86cce77f 100644
--- a/llvm/test/Transforms/ObjCARC/basic.ll
+++ b/llvm/test/Transforms/ObjCARC/basic.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -aa-pipeline=basic-aa -passes=objc-arc -S < %s | FileCheck %s
 
 target datalayout = "e-p:64:64:64"
@@ -31,11 +32,23 @@ declare ptr @objc_msgSend(ptr, ptr, ...)
 ; Simple retain+release pair deletion, with some intervening control
 ; flow and harmless instructions.
 
-; CHECK: define void @test0_precise(ptr %x, i1 %p) [[NUW:#[0-9]+]] {
-; CHECK: @llvm.objc.retain
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test0_precise(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test0_precise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -54,10 +67,21 @@ return:
   ret void
 }
 
-; CHECK: define void @test0_imprecise(ptr %x, i1 %p) [[NUW]] {
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test0_imprecise(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test0_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -81,11 +105,26 @@ return:
 
 ; TODO: Make the llvm.objc.release's argument be %0.
 
-; CHECK: define void @test1_precise(ptr %x, i1 %p, i1 %q) [[NUW]] {
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %x)
-; CHECK: {{^}}}
 define void @test1_precise(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test1_precise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br i1 [[Q]], label %[[RETURN]], label %[[ALT_RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[ALT_RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -108,11 +147,26 @@ alt_return:
   ret void
 }
 
-; CHECK: define void @test1_imprecise(ptr %x, i1 %p, i1 %q) [[NUW]] {
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test1_imprecise(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test1_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br i1 [[Q]], label %[[RETURN]], label %[[ALT_RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3:![0-9]+]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[ALT_RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -138,15 +192,24 @@ alt_return:
 
 ; Don't do partial elimination into two different CFG diamonds.
 
-; CHECK: define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
-; CHECK: entry:
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK-NOT: @llvm.objc.
-; CHECK: if.end5:
-; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]]
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test1b_precise(ptr %x, i1 %p, i1 %q) {
+; CHECK-LABEL: define void @test1b_precise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    tail call void @callee()
+; CHECK-NEXT:    br label %[[IF_END]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[IF_THEN3:.*]], label %[[IF_END5:.*]]
+; CHECK:       [[IF_THEN3]]:
+; CHECK-NEXT:    tail call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br label %[[IF_END5]]
+; CHECK:       [[IF_END5]]:
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   tail call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %if.then, label %if.end
@@ -167,15 +230,24 @@ if.end5:                                          ; preds = %if.then3, %if.end
   ret void
 }
 
-; CHECK-LABEL: define void @test1b_imprecise(
-; CHECK: entry:
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW:#[0-9]+]]
-; CHECK-NOT: @llvm.objc.
-; CHECK: if.end5:
-; CHECK:   tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE:[0-9]+]]
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test1b_imprecise(ptr %x, i1 %p, i1 %q) {
+; CHECK-LABEL: define void @test1b_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    tail call void @callee()
+; CHECK-NEXT:    br label %[[IF_END]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[IF_THEN3:.*]], label %[[IF_END5:.*]]
+; CHECK:       [[IF_THEN3]]:
+; CHECK-NEXT:    tail call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br label %[[IF_END5]]
+; CHECK:       [[IF_END5]]:
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   tail call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %if.then, label %if.end
@@ -200,11 +272,25 @@ if.end5:                                          ; preds = %if.then3, %if.end
 ; Like test0 but the pointer is passed to an intervening call,
 ; so the optimization is not safe.
 
-; CHECK-LABEL: define void @test2_precise(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test2_precise(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test2_precise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @use_pointer(ptr [[TMP0]])
+; CHECK-NEXT:    store float 3.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -225,11 +311,25 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test2_imprecise(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test2_imprecise(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test2_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @use_pointer(ptr [[TMP0]])
+; CHECK-NEXT:    store float 3.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -255,11 +355,20 @@ return:
 
 ; TODO: For now, assume this can't happen.
 
-; CHECK-LABEL: define void @test3_precise(
 ; TODO: @llvm.objc.retain(ptr %a)
 ; TODO: @llvm.objc.release
 ; CHECK: {{^}}}
 define void @test3_precise(ptr %x, ptr %q) nounwind {
+; CHECK-LABEL: define void @test3_precise(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[J:%.*]] = load volatile i1, ptr [[Q]], align 1
+; CHECK-NEXT:    br i1 [[J]], label %[[LOOP]], label %[[RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br label %loop
@@ -273,11 +382,20 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test3_imprecise(
 ; TODO: @llvm.objc.retain(ptr %a)
 ; TODO: @llvm.objc.release
 ; CHECK: {{^}}}
 define void @test3_imprecise(ptr %x, ptr %q) nounwind {
+; CHECK-LABEL: define void @test3_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[J:%.*]] = load volatile i1, ptr [[Q]], align 1
+; CHECK-NEXT:    br i1 [[J]], label %[[LOOP]], label %[[RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br label %loop
@@ -297,11 +415,22 @@ return:
 ; Like test0 but the retain is in a loop,
 ; so the optimization is not safe.
 
-; CHECK-LABEL: define void @test4_precise(
 ; TODO: @llvm.objc.retain(ptr %a)
 ; TODO: @llvm.objc.release
 ; CHECK: {{^}}}
 define void @test4_precise(ptr %x, ptr %q) nounwind {
+; CHECK-LABEL: define void @test4_precise(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[J:%.*]] = load volatile i1, ptr [[Q]], align 1
+; CHECK-NEXT:    br i1 [[J]], label %[[LOOP]], label %[[RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %loop
 
@@ -315,11 +444,22 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test4_imprecise(
 ; TODO: @llvm.objc.retain(ptr %a)
 ; TODO: @llvm.objc.release
 ; CHECK: {{^}}}
 define void @test4_imprecise(ptr %x, ptr %q) nounwind {
+; CHECK-LABEL: define void @test4_imprecise(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[J:%.*]] = load volatile i1, ptr [[Q]], align 1
+; CHECK-NEXT:    br i1 [[J]], label %[[LOOP]], label %[[RETURN:.*]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %loop
 
@@ -337,11 +477,17 @@ return:
 ; Like test0 but the pointer is conditionally passed to an intervening call,
 ; so the optimization is not safe.
 
-; CHECK-LABEL: define void @test5a(
-; CHECK: @llvm.objc.retain(ptr
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test5a(ptr %x, i1 %q, ptr %y) nounwind {
+; CHECK-LABEL: define void @test5a(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[Q:%.*]], ptr [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[S:%.*]] = select i1 [[Q]], ptr [[Y]], ptr [[X]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   %s = select i1 %q, ptr %y, ptr %0
@@ -351,11 +497,17 @@ entry:
   ret void
 }
 
-; CHECK-LABEL: define void @test5b(
-; CHECK: @llvm.objc.retain(ptr
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test5b(ptr %x, i1 %q, ptr %y) nounwind {
+; CHECK-LABEL: define void @test5b(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[Q:%.*]], ptr [[Y:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[S:%.*]] = select i1 [[Q]], ptr [[Y]], ptr [[X]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   %s = select i1 %q, ptr %y, ptr %0
@@ -369,16 +521,25 @@ entry:
 ; retain+release pair deletion, where the release happens on two different
 ; flow paths.
 
-; CHECK-LABEL: define void @test6a(
-; CHECK: entry:
-; CHECK:   tail call ptr @llvm.objc.retain
-; CHECK: t:
-; CHECK:   call void @llvm.objc.release
-; CHECK: f:
-; CHECK:   call void @llvm.objc.release
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test6a(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test6a(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -399,10 +560,22 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test6b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test6b(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test6b(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -423,16 +596,25 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test6c(
-; CHECK: entry:
-; CHECK:   tail call ptr @llvm.objc.retain
-; CHECK: t:
-; CHECK:   call void @llvm.objc.release
-; CHECK: f:
-; CHECK:   call void @llvm.objc.release
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test6c(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test6c(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -453,16 +635,25 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test6d(
-; CHECK: entry:
-; CHECK:   tail call ptr @llvm.objc.retain
-; CHECK: t:
-; CHECK:   call void @llvm.objc.release
-; CHECK: f:
-; CHECK:   call void @llvm.objc.release
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test6d(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test6d(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %p, label %t, label %f
@@ -487,17 +678,25 @@ return:
 ; retain+release pair deletion, where the retain happens on two different
 ; flow paths.
 
-; CHECK-LABEL:     define void @test7(
-; CHECK:     entry:
-; CHECK-NOT:   llvm.objc.
-; CHECK:     t:
-; CHECK:       call ptr @llvm.objc.retain
-; CHECK:     f:
-; CHECK:       call ptr @llvm.objc.retain
-; CHECK:     return:
-; CHECK:       call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test7(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test7(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -518,10 +717,22 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test7b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test7b(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test7b(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -544,15 +755,25 @@ return:
 
 ; Like test7, but there's a retain/retainBlock mismatch. Don't delete!
 
-; CHECK-LABEL: define void @test7c(
-; CHECK: t:
-; CHECK:   call ptr @llvm.objc.retainBlock
-; CHECK: f:
-; CHECK:   call ptr @llvm.objc.retain
-; CHECK: return:
-; CHECK:   call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test7c(ptr %x, i1 %p) nounwind {
+; CHECK-LABEL: define void @test7c(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @llvm.objc.retainBlock(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -576,20 +797,32 @@ return:
 ; retain+release pair deletion, where the retain and release both happen on
 ; different flow paths. Wild!
 
-; CHECK-LABEL: define void @test8a(
-; CHECK: entry:
-; CHECK: t:
-; CHECK:   @llvm.objc.retain
-; CHECK: f:
-; CHECK:   @llvm.objc.retain
-; CHECK: mid:
-; CHECK: u:
-; CHECK:   @llvm.objc.release
-; CHECK: g:
-; CHECK:   @llvm.objc.release
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test8a(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test8a(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID]]
+; CHECK:       [[MID]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[U:.*]], label %[[G:.*]]
+; CHECK:       [[U]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[G]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -620,10 +853,28 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test8b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test8b(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test8b(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID]]
+; CHECK:       [[MID]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[U:.*]], label %[[G:.*]]
+; CHECK:       [[U]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[G]]:
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -654,21 +905,30 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test8c(
-; CHECK: entry:
-; CHECK: t:
-; CHECK-NOT: @llvm.objc.
-; CHECK: f:
-; CHECK-NOT: @llvm.objc.
-; CHECK: mid:
-; CHECK: u:
-; CHECK:   @llvm.objc.retain
-; CHECK:   @llvm.objc.release
-; CHECK: g:
-; CHECK-NOT: @llvm.objc.
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test8c(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test8c(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID]]
+; CHECK:       [[MID]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[U:.*]], label %[[G:.*]]
+; CHECK:       [[U]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[G]]:
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -699,20 +959,32 @@ return:
   ret void
 }
 
-; CHECK-LABEL: define void @test8d(
-; CHECK: entry:
-; CHECK: t:
-; CHECK:   @llvm.objc.retain
-; CHECK: f:
-; CHECK:   @llvm.objc.retain
-; CHECK: mid:
-; CHECK: u:
-; CHECK:   @llvm.objc.release
-; CHECK: g:
-; CHECK:   @llvm.objc.release
-; CHECK: return:
-; CHECK: {{^}}}
 define void @test8d(ptr %x, i1 %p, i1 %q) nounwind {
+; CHECK-LABEL: define void @test8d(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[P:%.*]], i1 [[Q:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[P]], label %[[T:.*]], label %[[F:.*]]
+; CHECK:       [[T]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i8 3, ptr [[X]], align 1
+; CHECK-NEXT:    store float 2.000000e+00, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store i32 7, ptr [[X]], align 4
+; CHECK-NEXT:    br label %[[MID]]
+; CHECK:       [[MID]]:
+; CHECK-NEXT:    br i1 [[Q]], label %[[U:.*]], label %[[G:.*]]
+; CHECK:       [[U]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    br label %[[RETURN:.*]]
+; CHECK:       [[G]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %p, label %t, label %f
 
@@ -745,10 +1017,12 @@ return:
 
 ; Trivial retain+release pair deletion.
 
-; CHECK-LABEL: define void @test9(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test9(ptr %x) nounwind {
+; CHECK-LABEL: define void @test9(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @llvm.objc.release(ptr %0) nounwind
@@ -757,11 +1031,15 @@ entry:
 
 ; Retain+release pair, but on an unknown pointer relationship. Don't delete!
 
-; CHECK-LABEL: define void @test9b(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.release(ptr %s)
-; CHECK: {{^}}}
 define void @test9b(ptr %x, i1 %j, ptr %p) nounwind {
+; CHECK-LABEL: define void @test9b(
+; CHECK-SAME: ptr [[X:%.*]], i1 [[J:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[S:%.*]] = select i1 [[J]], ptr [[X]], ptr [[P]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[S]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   %s = select i1 %j, ptr %x, ptr %p
@@ -771,13 +1049,16 @@ entry:
 
 ; Trivial retain+release pair with intervening calls - don't delete!
 
-; CHECK-LABEL: define void @test10(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @callee
-; CHECK: @use_pointer
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test10(ptr %x) nounwind {
+; CHECK-LABEL: define void @test10(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @callee()
@@ -790,11 +1071,15 @@ entry:
 ; Also, add a tail keyword, since llvm.objc.retain can never be passed
 ; a stack argument.
 
-; CHECK-LABEL: define void @test11(
-; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
-; CHECK: {{^}}}
 define void @test11(ptr %x) nounwind {
+; CHECK-LABEL: define void @test11(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autorelease(ptr %0) nounwind
@@ -804,11 +1089,12 @@ entry:
 
 ; Same as test11 but with no use_pointer call. Delete the pair!
 
-; CHECK-LABEL: define void @test11a(
-; CHECK: entry:
-; CHECK-NEXT: ret void
-; CHECK: {{^}}}
 define void @test11a(ptr %x) nounwind {
+; CHECK-LABEL: define void @test11a(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autorelease(ptr %0) nounwind
@@ -819,11 +1105,14 @@ entry:
 ; since if the frontend emitted code for an __autoreleasing variable, we may
 ; want it to be in the autorelease pool.
 
-; CHECK-LABEL: define ptr @test11b(
-; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]
-; CHECK: {{^}}}
 define ptr @test11b(ptr %x) nounwind {
+; CHECK-LABEL: define ptr @test11b(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    ret ptr [[X]]
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autorelease(ptr %0) nounwind
@@ -833,13 +1122,17 @@ entry:
 ; We can not delete this retain, release since we do not have a post-dominating
 ; use of the release.
 
-; CHECK-LABEL: define void @test12(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain(ptr %x)
-; CHECK-NEXT: @llvm.objc.retain
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test12(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test12(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -851,13 +1144,16 @@ entry:
 
 ; Trivial retain,autorelease pair. Don't delete!
 
-; CHECK-LABEL: define void @test13(
-; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK: tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK: @use_pointer(ptr %x)
-; CHECK: call ptr @llvm.objc.autorelease(ptr %x) [[NUW]]
-; CHECK: {{^}}}
 define void @test13(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test13(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -868,16 +1164,17 @@ entry:
 
 ; Delete the retain+release pair.
 
-; CHECK-LABEL: define void @test13b(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain(ptr %x)
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test13b(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test13b(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -892,14 +1189,18 @@ entry:
 ; Don't delete the retain+release pair because there's an
 ; autoreleasePoolPop in the way.
 
-; CHECK-LABEL: define void @test13c(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc.autoreleasePoolPop
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @use_pointer
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test13c(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test13c(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.autoreleasePoolPop(ptr undef) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @llvm.objc.autoreleasePoolPop(ptr undef)
@@ -913,17 +1214,18 @@ entry:
 ; Like test13c, but there's an autoreleasePoolPush in the way, but that
 ; doesn't matter.
 
-; CHECK-LABEL: define void @test13d(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain(ptr %x)
-; CHECK-NEXT: @llvm.objc.autoreleasePoolPush
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test13d(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test13d(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autoreleasePoolPush() #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autoreleasePoolPush()
@@ -940,16 +1242,17 @@ entry:
 ; another release. But it is not known safe in the top down direction. We can
 ; not eliminate it.
 
-; CHECK-LABEL: define void @test14(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test14(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test14(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @use_pointer(ptr %x)
@@ -962,15 +1265,16 @@ entry:
 ; Trivial retain,autorelease pair with intervening call, but it's post-dominated
 ; by another release. Don't delete anything.
 
-; CHECK-LABEL: define void @test15(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain(ptr %x)
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @llvm.objc.autorelease(ptr %x)
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test15(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test15(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @use_pointer(ptr %x)
@@ -982,14 +1286,15 @@ entry:
 ; Trivial retain,autorelease pair, post-dominated
 ; by another release. Delete the retain and release.
 
-; CHECK-LABEL: define void @test15b(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.retain
-; CHECK-NEXT: @llvm.objc.autorelease
-; CHECK-NEXT: @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test15b(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test15b(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autorelease(ptr %x) nounwind
@@ -997,12 +1302,13 @@ entry:
   ret void
 }
 
-; CHECK-LABEL: define void @test15c(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: @llvm.objc.autorelease
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test15c(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @test15c(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.autorelease(ptr %x) nounwind
@@ -1012,14 +1318,29 @@ entry:
 
 ; Retain+release pairs in diamonds, all dominated by a retain.
 
-; CHECK-LABEL: define void @test16a(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK-NOT: @objc
-; CHECK: purple:
-; CHECK: @use_pointer
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test16a(i1 %a, i1 %b, ptr %x) {
+; CHECK-LABEL: define void @test16a(
+; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[A]], label %[[RED:.*]], label %[[ORANGE:.*]]
+; CHECK:       [[RED]]:
+; CHECK-NEXT:    br label %[[YELLOW:.*]]
+; CHECK:       [[ORANGE]]:
+; CHECK-NEXT:    br label %[[YELLOW]]
+; CHECK:       [[YELLOW]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br i1 [[B]], label %[[GREEN:.*]], label %[[BLUE:.*]]
+; CHECK:       [[GREEN]]:
+; CHECK-NEXT:    br label %[[PURPLE:.*]]
+; CHECK:       [[BLUE]]:
+; CHECK-NEXT:    br label %[[PURPLE]]
+; CHECK:       [[PURPLE]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %a, label %red, label %orange
@@ -1051,15 +1372,30 @@ purple:
   ret void
 }
 
-; CHECK-LABEL: define void @test16b(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK-NOT: @objc
-; CHECK: purple:
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @use_pointer
-; CHECK-NEXT: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test16b(i1 %a, i1 %b, ptr %x) {
+; CHECK-LABEL: define void @test16b(
+; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[A]], label %[[RED:.*]], label %[[ORANGE:.*]]
+; CHECK:       [[RED]]:
+; CHECK-NEXT:    br label %[[YELLOW:.*]]
+; CHECK:       [[ORANGE]]:
+; CHECK-NEXT:    br label %[[YELLOW]]
+; CHECK:       [[YELLOW]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br i1 [[B]], label %[[GREEN:.*]], label %[[BLUE:.*]]
+; CHECK:       [[GREEN]]:
+; CHECK-NEXT:    br label %[[PURPLE:.*]]
+; CHECK:       [[BLUE]]:
+; CHECK-NEXT:    br label %[[PURPLE]]
+; CHECK:       [[PURPLE]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %a, label %red, label %orange
@@ -1092,14 +1428,29 @@ purple:
   ret void
 }
 
-; CHECK-LABEL: define void @test16c(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK-NOT: @objc
-; CHECK: purple:
-; CHECK: @use_pointer
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test16c(i1 %a, i1 %b, ptr %x) {
+; CHECK-LABEL: define void @test16c(
+; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[A]], label %[[RED:.*]], label %[[ORANGE:.*]]
+; CHECK:       [[RED]]:
+; CHECK-NEXT:    br label %[[YELLOW:.*]]
+; CHECK:       [[ORANGE]]:
+; CHECK-NEXT:    br label %[[YELLOW]]
+; CHECK:       [[YELLOW]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br i1 [[B]], label %[[GREEN:.*]], label %[[BLUE:.*]]
+; CHECK:       [[GREEN]]:
+; CHECK-NEXT:    br label %[[PURPLE:.*]]
+; CHECK:       [[BLUE]]:
+; CHECK-NEXT:    br label %[[PURPLE]]
+; CHECK:       [[PURPLE]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %a, label %red, label %orange
@@ -1131,11 +1482,31 @@ purple:
   ret void
 }
 
-; CHECK-LABEL: define void @test16d(
-; CHECK: @llvm.objc.retain(ptr %x)
-; CHECK: @llvm.objc
-; CHECK: {{^}}}
 define void @test16d(i1 %a, i1 %b, ptr %x) {
+; CHECK-LABEL: define void @test16d(
+; CHECK-SAME: i1 [[A:%.*]], i1 [[B:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[A]], label %[[RED:.*]], label %[[ORANGE:.*]]
+; CHECK:       [[RED]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[YELLOW:.*]]
+; CHECK:       [[ORANGE]]:
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[YELLOW]]
+; CHECK:       [[YELLOW]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    br i1 [[B]], label %[[GREEN:.*]], label %[[BLUE:.*]]
+; CHECK:       [[GREEN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[PURPLE:.*]]
+; CHECK:       [[BLUE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    br label %[[PURPLE]]
+; CHECK:       [[PURPLE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   br i1 %a, label %red, label %orange
@@ -1167,10 +1538,10 @@ purple:
 
 ; Delete no-ops.
 
-; CHECK-LABEL: define void @test18(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test18() {
+; CHECK-LABEL: define void @test18() {
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr null)
   call void @llvm.objc.release(ptr null)
   call ptr @llvm.objc.autorelease(ptr null)
@@ -1179,10 +1550,10 @@ define void @test18() {
 
 ; Delete no-ops where undef can be assumed to be null.
 
-; CHECK-LABEL: define void @test18b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test18b() {
+; CHECK-LABEL: define void @test18b() {
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr undef)
   call void @llvm.objc.release(ptr undef)
   call ptr @llvm.objc.autorelease(ptr undef)
@@ -1192,14 +1563,16 @@ define void @test18b() {
 ; Replace uses of arguments with uses of return values, to reduce
 ; register pressure.
 
-; CHECK: define void @test19(ptr %y) {
-; CHECK:   %0 = tail call ptr @llvm.objc.retain(ptr %y)
-; CHECK:   call void @use_pointer(ptr %y)
-; CHECK:   call void @use_pointer(ptr %y)
-; CHECK:   call void @llvm.objc.release(ptr %y)
-; CHECK:   ret void
-; CHECK: {{^}}}
 define void @test19(ptr %y) {
+; CHECK-LABEL: define void @test19(
+; CHECK-SAME: ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[Y]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[Y]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %y) nounwind
   call void @use_pointer(ptr %y)
@@ -1210,24 +1583,37 @@ entry:
 
 ; Bitcast insertion
 
-; CHECK-LABEL: define void @test20(
-; CHECK: %tmp1 = tail call ptr @llvm.objc.retain(ptr %self) [[NUW]]
-; CHECK-NEXT: invoke
-; CHECK: {{^}}}
 define void @test20(ptr %self) personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: define void @test20(
+; CHECK-SAME: ptr [[SELF:%.*]]) personality ptr @__gxx_personality_v0 {
+; CHECK-NEXT:  [[IF_THEN12:.*]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[SELF]]) #[[ATTR0]]
+; CHECK-NEXT:    invoke void @invokee()
+; CHECK-NEXT:            to label %[[INVOKE_CONT23:.*]] unwind label %[[LPAD20:.*]]
+; CHECK:       [[INVOKE_CONT23]]:
+; CHECK-NEXT:    invoke void @invokee()
+; CHECK-NEXT:            to label %[[IF_END:.*]] unwind label %[[LPAD20]]
+; CHECK:       [[LPAD20]]:
+; CHECK-NEXT:    [[TMP502:%.*]] = phi ptr [ undef, %[[INVOKE_CONT23]] ], [ [[SELF]], %[[IF_THEN12]] ]
+; CHECK-NEXT:    [[EXN:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    unreachable
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    ret void
+;
 if.then12:
   %tmp1 = call ptr @llvm.objc.retain(ptr %self) nounwind
   invoke void @invokee()
-          to label %invoke.cont23 unwind label %lpad20
+  to label %invoke.cont23 unwind label %lpad20
 
 invoke.cont23:                                    ; preds = %if.then12
   invoke void @invokee()
-          to label %if.end unwind label %lpad20
+  to label %if.end unwind label %lpad20
 
 lpad20:                                           ; preds = %invoke.cont23, %if.then12
   %tmp502 = phi ptr [ undef, %invoke.cont23 ], [ %self, %if.then12 ]
   %exn = landingpad {ptr, i32}
-           cleanup
+  cleanup
   unreachable
 
 if.end:                                           ; preds = %invoke.cont23
@@ -1237,11 +1623,12 @@ if.end:                                           ; preds = %invoke.cont23
 ; Delete a redundant retain,autorelease when forwaring a call result
 ; directly to a return value.
 
-; CHECK-LABEL: define ptr @test21(
-; CHECK: call ptr @returner()
-; CHECK-NEXT: ret ptr %call
-; CHECK-NEXT: }
 define ptr @test21() {
+; CHECK-LABEL: define ptr @test21() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    ret ptr [[CALL]]
+;
 entry:
   %call = call ptr @returner()
   %0 = call ptr @llvm.objc.retain(ptr %call) nounwind
@@ -1251,14 +1638,18 @@ entry:
 
 ; Move an objc call up through a phi that has null operands.
 
-; CHECK-LABEL: define void @test22(
-; CHECK: B:
-; CHECK:   call void @llvm.objc.release(ptr %p)
-; CHECK:   br label %C
-; CHECK: C:                                                ; preds = %B, %A
-; CHECK-NOT: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test22(ptr %p, i1 %a) {
+; CHECK-LABEL: define void @test22(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[A:%.*]]) {
+; CHECK-NEXT:    br i1 [[A]], label %[[A:.*]], label %[[B:.*]]
+; CHECK:       [[A]]:
+; CHECK-NEXT:    br label %[[C:.*]]
+; CHECK:       [[B]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[C]]
+; CHECK:       [[C]]:
+; CHECK-NEXT:    ret void
+;
   br i1 %a, label %A, label %B
 A:
   br label %C
@@ -1272,11 +1663,19 @@ C:
 
 ; Do not move an llvm.objc.release that doesn't have the clang.imprecise_release tag.
 
-; CHECK-LABEL: define void @test22_precise(
-; CHECK: %[[P0:.*]] = phi ptr
-; CHECK: call void @llvm.objc.release(ptr %[[P0]])
-; CHECK: ret void
 define void @test22_precise(ptr %p, i1 %a) {
+; CHECK-LABEL: define void @test22_precise(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[A:%.*]]) {
+; CHECK-NEXT:    br i1 [[A]], label %[[A:.*]], label %[[B:.*]]
+; CHECK:       [[A]]:
+; CHECK-NEXT:    br label %[[C:.*]]
+; CHECK:       [[B]]:
+; CHECK-NEXT:    br label %[[C]]
+; CHECK:       [[C]]:
+; CHECK-NEXT:    [[H:%.*]] = phi ptr [ null, %[[A]] ], [ [[P]], %[[B]] ]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[H]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   br i1 %a, label %A, label %B
 A:
   br label %C
@@ -1290,11 +1689,15 @@ C:
 
 ; Any call can decrement a retain count.
 
-; CHECK-LABEL: define void @test24(
-; CHECK: @llvm.objc.retain(ptr %a)
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test24(ptr %r, ptr %a) {
+; CHECK-LABEL: define void @test24(
+; CHECK-SAME: ptr [[R:%.*]], ptr [[A:%.*]]) {
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[R]])
+; CHECK-NEXT:    [[Q:%.*]] = load i8, ptr [[A]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %a)
   call void @use_pointer(ptr %r)
   %q = load i8, ptr %a
@@ -1305,14 +1708,20 @@ define void @test24(ptr %r, ptr %a) {
 ; Don't move a retain/release pair if the release can be moved
 ; but the retain can't be moved to balance it.
 
-; CHECK-LABEL: define void @test25(
-; CHECK: entry:
-; CHECK:   call ptr @llvm.objc.retain(ptr %p)
-; CHECK: true:
-; CHECK: done:
-; CHECK:   call void @llvm.objc.release(ptr %p)
-; CHECK: {{^}}}
 define void @test25(ptr %p, i1 %x) {
+; CHECK-LABEL: define void @test25(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -1330,14 +1739,20 @@ done:
 ; Don't move a retain/release pair if the retain can be moved
 ; but the release can't be moved to balance it.
 
-; CHECK-LABEL: define void @test26(
-; CHECK: entry:
-; CHECK:   call ptr @llvm.objc.retain(ptr %p)
-; CHECK: true:
-; CHECK: done:
-; CHECK:   call void @llvm.objc.release(ptr %p)
-; CHECK: {{^}}}
 define void @test26(ptr %p, i1 %x) {
+; CHECK-LABEL: define void @test26(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1354,15 +1769,20 @@ done:
 
 ; Don't sink the retain,release into the loop.
 
-; CHECK-LABEL: define void @test27(
-; CHECK: entry:
-; CHECK: call ptr @llvm.objc.retain(ptr %p)
-; CHECK: loop:
-; CHECK-NOT: @llvm.objc.
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test27(ptr %p, i1 %x, i1 %y) {
+; CHECK-LABEL: define void @test27(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], i1 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[LOOP:.*]], label %[[DONE:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Y]], label %[[DONE]], label %[[LOOP]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %loop, label %done
@@ -1379,17 +1799,20 @@ done:
 
 ; Trivial code motion case: Triangle.
 
-; CHECK-LABEL: define void @test28(
-; CHECK-NOT: @llvm.objc.
-; CHECK: true:
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: call void @llvm.objc.release
-; CHECK: done:
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test28(ptr %p, i1 %x) {
+; CHECK-LABEL: define void @test28(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1407,18 +1830,21 @@ done:
 ; Trivial code motion case: Triangle, but no metadata. Don't move past
 ; unrelated memory references!
 
-; CHECK-LABEL: define void @test28b(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK-NOT: @llvm.objc.
-; CHECK: call void @callee()
-; CHECK-NOT: @llvm.objc.
-; CHECK: store
-; CHECK-NOT: @llvm.objc.
-; CHECK: done:
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test28b(ptr %p, i1 %x, ptr noalias %t) {
+; CHECK-LABEL: define void @test28b(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr noalias [[T:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    store i8 0, ptr [[T]], align 1
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1437,17 +1863,21 @@ done:
 ; Trivial code motion case: Triangle, with metadata. Do move past
 ; unrelated memory references! And preserve the metadata.
 
-; CHECK-LABEL: define void @test28c(
-; CHECK-NOT: @llvm.objc.
-; CHECK: true:
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: call void @llvm.objc.release(ptr %p) [[NUW]], !clang.imprecise_release
-; CHECK: done:
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test28c(ptr %p, i1 %x, ptr noalias %t) {
+; CHECK-LABEL: define void @test28c(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr noalias [[T:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    store i8 0, ptr [[T]], align 1
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1465,17 +1895,23 @@ done:
 
 ; Like test28. but with two releases.
 
-; CHECK-LABEL: define void @test29(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: ohno:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test29(ptr %p, i1 %x, i1 %y) {
+; CHECK-LABEL: define void @test29(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], i1 [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Y]], label %[[DONE]], label %[[OHNO:.*]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[OHNO]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1497,18 +1933,25 @@ ohno:
 ; Basic case with the use and call in a diamond
 ; with an extra release.
 
-; CHECK-LABEL: define void @test30(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: false:
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: ohno:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test30(ptr %p, i1 %x, i1 %y, i1 %z) {
+; CHECK-LABEL: define void @test30(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], i1 [[Y:%.*]], i1 [[Z:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Y]], label %[[DONE:.*]], label %[[OHNO:.*]]
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    br i1 [[Z]], label %[[DONE]], label %[[OHNO]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[OHNO]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %false
@@ -1532,17 +1975,21 @@ ohno:
 
 ; Basic case with a mergeable release.
 
-; CHECK-LABEL: define void @test31(
-; CHECK: call ptr @llvm.objc.retain(ptr %p)
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: true:
-; CHECK: call void @llvm.objc.release
-; CHECK: false:
-; CHECK: call void @llvm.objc.release
-; CHECK: ret void
-; CHECK: {{^}}}
 define void @test31(ptr %p, i1 %x) {
+; CHECK-LABEL: define void @test31(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -1558,15 +2005,20 @@ false:
 
 ; Don't consider bitcasts or getelementptrs direct uses.
 
-; CHECK-LABEL: define void @test32(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: call void @callee()
-; CHECK: store
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test32(ptr %p, i1 %x) {
+; CHECK-LABEL: define void @test32(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1583,15 +2035,20 @@ done:
 
 ; Do consider icmps to be direct uses.
 
-; CHECK-LABEL: define void @test33(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: call void @callee()
-; CHECK: icmp
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test33(ptr %p, i1 %x, ptr %y) {
+; CHECK-LABEL: define void @test33(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[V:%.*]] = icmp eq ptr [[P]], [[Y]]
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1609,13 +2066,19 @@ done:
 ; Delete retain,release if there's just a possible dec and we have imprecise
 ; releases.
 
-; CHECK-LABEL: define void @test34a(
-; CHECK:   call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: done:
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test34a(ptr %p, i1 %x, ptr %y) {
+; CHECK-LABEL: define void @test34a(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1629,10 +2092,17 @@ done:
   ret void
 }
 
-; CHECK-LABEL: define void @test34b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test34b(ptr %p, i1 %x, ptr %y) {
+; CHECK-LABEL: define void @test34b(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1651,14 +2121,19 @@ done:
 ; release.
 
 ; Precise.
-; CHECK-LABEL: define void @test35a(
-; CHECK: entry:
-; CHECK:   call ptr @llvm.objc.retain
-; CHECK: true:
-; CHECK: done:
-; CHECK:   call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test35a(ptr %p, i1 %x, ptr %y) {
+; CHECK-LABEL: define void @test35a(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[F0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    [[V:%.*]] = icmp eq ptr [[P]], [[Y]]
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1673,10 +2148,17 @@ done:
 }
 
 ; Imprecise.
-; CHECK-LABEL: define void @test35b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test35b(ptr %p, i1 %x, ptr %y) {
+; CHECK-LABEL: define void @test35b(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[X]], label %[[TRUE:.*]], label %[[DONE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    [[V:%.*]] = icmp eq ptr [[P]], [[Y]]
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %f0 = call ptr @llvm.objc.retain(ptr %p)
   br i1 %x, label %true, label %done
@@ -1692,14 +2174,16 @@ done:
 
 ; Delete a retain,release if there's no actual use and we have precise release.
 
-; CHECK-LABEL: define void @test36a(
-; CHECK: @llvm.objc.retain
-; CHECK: call void @callee()
-; CHECK-NOT: @llvm.objc.
-; CHECK: call void @callee()
-; CHECK: @llvm.objc.release
-; CHECK: {{^}}}
 define void @test36a(ptr %p) {
+; CHECK-LABEL: define void @test36a(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -1710,10 +2194,14 @@ entry:
 
 ; Like test36, but with metadata.
 
-; CHECK-LABEL: define void @test36b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test36b(ptr %p) {
+; CHECK-LABEL: define void @test36b(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -1724,10 +2212,34 @@ entry:
 
 ; Be aggressive about analyzing phis to eliminate possible uses.
 
-; CHECK-LABEL: define void @test38(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test38(ptr %p, i1 %u, i1 %m, ptr %z, ptr %y, ptr %x, ptr %w) {
+; CHECK-LABEL: define void @test38(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[U:%.*]], i1 [[M:%.*]], ptr [[Z:%.*]], ptr [[Y:%.*]], ptr [[X:%.*]], ptr [[W:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br i1 [[U]], label %[[TRUE:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    br i1 [[M]], label %[[A:.*]], label %[[B:.*]]
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    br i1 [[M]], label %[[C:.*]], label %[[D:.*]]
+; CHECK:       [[A]]:
+; CHECK-NEXT:    br label %[[E:.*]]
+; CHECK:       [[B]]:
+; CHECK-NEXT:    br label %[[E]]
+; CHECK:       [[C]]:
+; CHECK-NEXT:    br label %[[F:.*]]
+; CHECK:       [[D]]:
+; CHECK-NEXT:    br label %[[F]]
+; CHECK:       [[E]]:
+; CHECK-NEXT:    [[J:%.*]] = phi ptr [ [[Z]], %[[A]] ], [ [[Y]], %[[B]] ]
+; CHECK-NEXT:    br label %[[G:.*]]
+; CHECK:       [[F]]:
+; CHECK-NEXT:    [[K:%.*]] = phi ptr [ [[W]], %[[C]] ], [ [[X]], %[[D]] ]
+; CHECK-NEXT:    br label %[[G]]
+; CHECK:       [[G]]:
+; CHECK-NEXT:    [[H:%.*]] = phi ptr [ [[J]], %[[E]] ], [ [[K]], %[[F]] ]
+; CHECK-NEXT:    call void @use_pointer(ptr [[H]])
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   br i1 %u, label %true, label %false
@@ -1758,10 +2270,16 @@ g:
 
 ; Delete retain,release pairs around loops.
 
-; CHECK-LABEL: define void @test39(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test39(ptr %p, i1 %arg) {
+; CHECK-LABEL: define void @test39(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    br i1 [[ARG]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   br label %loop
@@ -1776,10 +2294,17 @@ exit:                                             ; preds = %loop
 
 ; Delete retain,release pairs around loops containing uses.
 
-; CHECK-LABEL: define void @test39b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test39b(ptr %p, i1 %arg) {
+; CHECK-LABEL: define void @test39b(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[ARG]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   br label %loop
@@ -1795,10 +2320,17 @@ exit:                                             ; preds = %loop
 
 ; Delete retain,release pairs around loops containing potential decrements.
 
-; CHECK-LABEL: define void @test39c(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test39c(ptr %p, i1 %arg) {
+; CHECK-LABEL: define void @test39c(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    br i1 [[ARG]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   br label %loop
@@ -1815,10 +2347,17 @@ exit:                                             ; preds = %loop
 ; Delete retain,release pairs around loops even if
 ; the successors are in a different order.
 
-; CHECK-LABEL: define void @test40(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test40(ptr %p, i1 %arg) {
+; CHECK-LABEL: define void @test40(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[ARG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    br i1 [[ARG]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   br label %loop
@@ -1835,18 +2374,19 @@ exit:                                             ; preds = %loop
 ; Do the known-incremented retain+release elimination even if the pointer
 ; is also autoreleased.
 
-; CHECK-LABEL: define void @test42(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
-; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @llvm.objc.release(ptr %p)
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test42(ptr %p) {
+; CHECK-LABEL: define void @test42(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   call ptr @llvm.objc.autorelease(ptr %p)
@@ -1863,18 +2403,19 @@ entry:
 ; Don't the known-incremented retain+release elimination if the pointer is
 ; autoreleased and there's an autoreleasePoolPop.
 
-; CHECK-LABEL: define void @test43(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
-; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
-; CHECK-NEXT: call ptr @llvm.objc.retain
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @llvm.objc.autoreleasePoolPop(ptr undef)
-; CHECK-NEXT: call void @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test43(ptr %p) {
+; CHECK-LABEL: define void @test43(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @llvm.objc.autoreleasePoolPop(ptr undef) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   call ptr @llvm.objc.autorelease(ptr %p)
@@ -1889,18 +2430,19 @@ entry:
 ; Do the known-incremented retain+release elimination if the pointer is
 ; autoreleased and there's an autoreleasePoolPush.
 
-; CHECK-LABEL: define void @test43b(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: call ptr @llvm.objc.retain(ptr %p)
-; CHECK-NEXT: call ptr @llvm.objc.autorelease(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call ptr @llvm.objc.autoreleasePoolPush()
-; CHECK-NEXT: call void @use_pointer(ptr %p)
-; CHECK-NEXT: call void @llvm.objc.release
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test43b(ptr %p) {
+; CHECK-LABEL: define void @test43b(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call ptr @llvm.objc.autoreleasePoolPush() #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   call ptr @llvm.objc.autorelease(ptr %p)
@@ -1916,10 +2458,11 @@ entry:
 
 ; Do retain+release elimination for non-provenance pointers.
 
-; CHECK-LABEL: define void @test44(
-; CHECK-NOT: llvm.objc.
-; CHECK: {{^}}}
 define void @test44(ptr %pp) {
+; CHECK-LABEL: define void @test44(
+; CHECK-SAME: ptr [[PP:%.*]]) {
+; CHECK-NEXT:    ret void
+;
   %p = load ptr, ptr %pp
   %q = call ptr @llvm.objc.retain(ptr %p)
   call void @llvm.objc.release(ptr %q)
@@ -1929,13 +2472,17 @@ define void @test44(ptr %pp) {
 ; Don't delete retain+release with an unknown-provenance
 ; may-alias llvm.objc.release between them.
 
-; CHECK-LABEL: define void @test45(
-; CHECK: call ptr @llvm.objc.retain(ptr %p)
-; CHECK: call void @llvm.objc.release(ptr %q)
-; CHECK: call void @use_pointer(ptr %p)
-; CHECK: call void @llvm.objc.release(ptr %p)
-; CHECK: {{^}}}
 define void @test45(ptr %pp, ptr %qq) {
+; CHECK-LABEL: define void @test45(
+; CHECK-SAME: ptr [[PP:%.*]], ptr [[QQ:%.*]]) {
+; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PP]], align 8
+; CHECK-NEXT:    [[Q:%.*]] = load ptr, ptr [[QQ]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Q]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %p = load ptr, ptr %pp
   %q = load ptr, ptr %qq
   call ptr @llvm.objc.retain(ptr %p)
@@ -1947,12 +2494,19 @@ define void @test45(ptr %pp, ptr %qq) {
 
 ; Don't delete retain and autorelease here.
 
-; CHECK-LABEL: define void @test46(
-; CHECK: tail call ptr @llvm.objc.retain(ptr %p) [[NUW]]
-; CHECK: true:
-; CHECK: call ptr @llvm.objc.autorelease(ptr %p) [[NUW]]
-; CHECK: {{^}}}
 define void @test46(ptr %p, i1 %a) {
+; CHECK-LABEL: define void @test46(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[A:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[A]], label %[[TRUE:.*]], label %[[FALSE:.*]]
+; CHECK:       [[TRUE]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[P]])
+; CHECK-NEXT:    ret void
+; CHECK:       [[FALSE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %p)
   br i1 %a, label %true, label %false
@@ -1968,33 +2522,33 @@ false:
 
 ; Delete no-op cast calls.
 
-; CHECK-LABEL: define ptr @test47(
-; CHECK-NOT: call
-; CHECK: ret ptr %p
-; CHECK: {{^}}}
 define ptr @test47(ptr %p) nounwind {
+; CHECK-LABEL: define ptr @test47(
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    ret ptr [[P]]
+;
   %x = call ptr @llvm.objc.retainedObject(ptr %p)
   ret ptr %x
 }
 
 ; Delete no-op cast calls.
 
-; CHECK-LABEL: define ptr @test48(
-; CHECK-NOT: call
-; CHECK: ret ptr %p
-; CHECK: {{^}}}
 define ptr @test48(ptr %p) nounwind {
+; CHECK-LABEL: define ptr @test48(
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    ret ptr [[P]]
+;
   %x = call ptr @llvm.objc.unretainedObject(ptr %p)
   ret ptr %x
 }
 
 ; Delete no-op cast calls.
 
-; CHECK-LABEL: define ptr @test49(
-; CHECK-NOT: call
-; CHECK: ret ptr %p
-; CHECK: {{^}}}
 define ptr @test49(ptr %p) nounwind {
+; CHECK-LABEL: define ptr @test49(
+; CHECK-SAME: ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    ret ptr [[P]]
+;
   %x = call ptr @llvm.objc.unretainedPointer(ptr %p)
   ret ptr %x
 }
@@ -2002,14 +2556,15 @@ define ptr @test49(ptr %p) nounwind {
 ; Do delete retain+release with intervening stores of the address value if we
 ; have imprecise release attached to llvm.objc.release.
 
-; CHECK-LABEL:      define void @test50a(
-; CHECK-NEXT:   call ptr @llvm.objc.retain
-; CHECK-NEXT:   call void @callee
-; CHECK-NEXT:   store
-; CHECK-NEXT:   call void @llvm.objc.release
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test50a(ptr %p, ptr %pp) {
+; CHECK-LABEL: define void @test50a(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[PP:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store ptr [[P]], ptr [[PP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
   store ptr %p, ptr %pp
@@ -2017,10 +2572,13 @@ define void @test50a(ptr %p, ptr %pp) {
   ret void
 }
 
-; CHECK-LABEL: define void @test50b(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test50b(ptr %p, ptr %pp) {
+; CHECK-LABEL: define void @test50b(
+; CHECK-SAME: ptr [[P:%.*]], ptr [[PP:%.*]]) {
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store ptr [[P]], ptr [[PP]], align 8
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
   store ptr %p, ptr %pp
@@ -2032,12 +2590,15 @@ define void @test50b(ptr %p, ptr %pp) {
 ; Don't delete retain+release with intervening stores through the
 ; address value.
 
-; CHECK-LABEL: define void @test51a(
-; CHECK: call ptr @llvm.objc.retain(ptr %p)
-; CHECK: call void @llvm.objc.release(ptr %p)
-; CHECK: ret void
-; CHECK: {{^}}}
 define void @test51a(ptr %p) {
+; CHECK-LABEL: define void @test51a(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
   store i8 0, ptr %p
@@ -2045,12 +2606,15 @@ define void @test51a(ptr %p) {
   ret void
 }
 
-; CHECK-LABEL: define void @test51b(
-; CHECK: call ptr @llvm.objc.retain(ptr %p)
-; CHECK: call void @llvm.objc.release(ptr %p)
-; CHECK: ret void
-; CHECK: {{^}}}
 define void @test51b(ptr %p) {
+; CHECK-LABEL: define void @test51b(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    store i8 0, ptr [[P]], align 1
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
   store i8 0, ptr %p
@@ -2061,14 +2625,17 @@ define void @test51b(ptr %p) {
 ; Don't delete retain+release with intervening use of a pointer of
 ; unknown provenance.
 
-; CHECK-LABEL: define void @test52a(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void @callee()
-; CHECK: call void @use_pointer(ptr %z)
-; CHECK: call void @llvm.objc.release
-; CHECK: ret void
-; CHECK: {{^}}}
 define void @test52a(ptr %zz, ptr %pp) {
+; CHECK-LABEL: define void @test52a(
+; CHECK-SAME: ptr [[ZZ:%.*]], ptr [[PP:%.*]]) {
+; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[Z:%.*]] = load ptr, ptr [[ZZ]], align 8
+; CHECK-NEXT:    call void @use_pointer(ptr [[Z]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %p = load ptr, ptr %pp
   %1 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -2078,14 +2645,17 @@ define void @test52a(ptr %zz, ptr %pp) {
   ret void
 }
 
-; CHECK-LABEL: define void @test52b(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void @callee()
-; CHECK: call void @use_pointer(ptr %z)
-; CHECK: call void @llvm.objc.release
-; CHECK: ret void
-; CHECK: {{^}}}
 define void @test52b(ptr %zz, ptr %pp) {
+; CHECK-LABEL: define void @test52b(
+; CHECK-SAME: ptr [[ZZ:%.*]], ptr [[PP:%.*]]) {
+; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[Z:%.*]] = load ptr, ptr [[ZZ]], align 8
+; CHECK-NEXT:    call void @use_pointer(ptr [[Z]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %p = load ptr, ptr %pp
   %1 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -2100,10 +2670,17 @@ define void @test52b(ptr %zz, ptr %pp) {
 ; Oops. That's wrong. Clang sometimes uses function types gratuitously.
 ; See rdar://10551239.
 
-; CHECK-LABEL: define void @test53(
-; CHECK: @llvm.objc.
-; CHECK: {{^}}}
 define void @test53(ptr %zz, ptr %pp) {
+; CHECK-LABEL: define void @test53(
+; CHECK-SAME: ptr [[ZZ:%.*]], ptr [[PP:%.*]]) {
+; CHECK-NEXT:    [[P:%.*]] = load ptr, ptr [[PP]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[Z:%.*]] = load ptr, ptr [[ZZ]], align 8
+; CHECK-NEXT:    call void @callee_fnptr(ptr [[Z]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %p = load ptr, ptr %pp
   %1 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -2115,12 +2692,12 @@ define void @test53(ptr %zz, ptr %pp) {
 
 ; Convert autorelease to release if the value is unused.
 
-; CHECK-LABEL: define void @test54(
-; CHECK: call ptr @returner()
-; CHECK-NEXT: call void @llvm.objc.release(ptr %t) [[NUW]], !clang.imprecise_release ![[RELEASE]]
-; CHECK-NEXT: ret void
-; CHECK: {{^}}}
 define void @test54() {
+; CHECK-LABEL: define void @test54() {
+; CHECK-NEXT:    [[T:%.*]] = call ptr @returner()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[T]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
   %t = call ptr @returner()
   call ptr @llvm.objc.autorelease(ptr %t)
   ret void
@@ -2128,10 +2705,14 @@ define void @test54() {
 
 ; Nested retain+release pairs. Delete them both.
 
-; CHECK-LABEL: define void @test55(
-; CHECK-NOT: @objc
-; CHECK: {{^}}}
 define void @test55(ptr %x) {
+; CHECK-LABEL: define void @test55(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %x) nounwind
   %1 = call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -2145,17 +2726,21 @@ entry:
 ; can be partially eliminated. Plus an extra outer pair to
 ; eliminate, for fun.
 
-; CHECK-LABEL: define void @test56(
-; CHECK-NOT: @objc
-; CHECK: if.then:
-; CHECK-NEXT: %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK-NEXT: tail call void @use_pointer(ptr %x)
-; CHECK-NEXT: tail call void @use_pointer(ptr %x)
-; CHECK-NEXT: tail call void @llvm.objc.release(ptr %x) [[NUW]], !clang.imprecise_release ![[RELEASE]]
-; CHECK-NEXT: br label %if.end
-; CHECK-NOT: @objc
-; CHECK: {{^}}}
 define void @test56(ptr %x, i32 %n) {
+; CHECK-LABEL: define void @test56(
+; CHECK-SAME: ptr [[X:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i32 [[N]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[IF_END:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    tail call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    tail call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[IF_END]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
   %1 = tail call ptr @llvm.objc.retain(ptr %0) nounwind
@@ -2179,18 +2764,19 @@ if.end:                                           ; preds = %entry, %if.then
 ; unnecessary because the presence of the second one means that the first one
 ; won't be deleting the object.
 
-; CHECK-LABEL:      define void @test57(
-; CHECK-NEXT: entry:
-; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test57(ptr %x) nounwind {
+; CHECK-LABEL: define void @test57(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -2207,14 +2793,15 @@ entry:
 ; An adjacent retain+release pair is sufficient even if it will be
 ; removed itself.
 
-; CHECK-LABEL:      define void @test58(
-; CHECK-NEXT: entry:
-; CHECK-NEXT:   @llvm.objc.retain
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test58(ptr %x) nounwind {
+; CHECK-LABEL: define void @test58(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %x) nounwind
   call ptr @llvm.objc.retain(ptr %x) nounwind
@@ -2228,15 +2815,16 @@ entry:
 
 ; Don't delete the second retain+release pair in an adjacent set.
 
-; CHECK-LABEL:      define void @test59(
-; CHECK-NEXT: entry:
-; CHECK-NEXT:   %0 = tail call ptr @llvm.objc.retain(ptr %x) [[NUW]]
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @use_pointer(ptr %x)
-; CHECK-NEXT:   call void @llvm.objc.release(ptr %x) [[NUW]]
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test59(ptr %x) nounwind {
+; CHECK-LABEL: define void @test59(
+; CHECK-SAME: ptr [[X:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    call void @use_pointer(ptr [[X]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %a = call ptr @llvm.objc.retain(ptr %x) nounwind
   call void @llvm.objc.release(ptr %x) nounwind
@@ -2255,11 +2843,16 @@ entry:
 ; We have a precise lifetime retain/release here. We can not remove them since
 ; @something is not constant.
 
-; CHECK-LABEL: define void @test60a(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void @llvm.objc.release
-; CHECK: {{^}}}
 define void @test60a() {
+; CHECK-LABEL: define void @test60a() {
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr @constptr, align 8
+; CHECK-NEXT:    [[S:%.*]] = load ptr, ptr @something, align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[S]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[T]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[S]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   %s = load ptr, ptr @something
   call ptr @llvm.objc.retain(ptr %s)
@@ -2269,12 +2862,15 @@ define void @test60a() {
   ret void
 }
 
-; CHECK-LABEL: define void @test60b(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK-NOT: call ptr @llvm.objc.retain
-; CHECK-NOT: call ptr @llvm.objc.release
-; CHECK: {{^}}}
 define void @test60b() {
+; CHECK-LABEL: define void @test60b() {
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr @constptr, align 8
+; CHECK-NEXT:    [[S:%.*]] = load ptr, ptr @something, align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[T]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   %s = load ptr, ptr @something
   call ptr @llvm.objc.retain(ptr %t)
@@ -2285,10 +2881,13 @@ define void @test60b() {
   ret void
 }
 
-; CHECK-LABEL: define void @test60c(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test60c() {
+; CHECK-LABEL: define void @test60c() {
+; CHECK-NEXT:    [[S:%.*]] = load ptr, ptr @something, align 8
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   %s = load ptr, ptr @something
   call ptr @llvm.objc.retain(ptr %t)
@@ -2298,10 +2897,13 @@ define void @test60c() {
   ret void
 }
 
-; CHECK-LABEL: define void @test60d(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test60d() {
+; CHECK-LABEL: define void @test60d() {
+; CHECK-NEXT:    [[S:%.*]] = load ptr, ptr @something, align 8
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   %s = load ptr, ptr @something
   call ptr @llvm.objc.retain(ptr %t)
@@ -2311,10 +2913,13 @@ define void @test60d() {
   ret void
 }
 
-; CHECK-LABEL: define void @test60e(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test60e() {
+; CHECK-LABEL: define void @test60e() {
+; CHECK-NEXT:    [[S:%.*]] = load ptr, ptr @something, align 8
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[S]])
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   %s = load ptr, ptr @something
   call ptr @llvm.objc.retain(ptr %t)
@@ -2327,10 +2932,13 @@ define void @test60e() {
 ; Constant pointers to objects don't need to be considered related to other
 ; pointers.
 
-; CHECK-LABEL: define void @test61(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test61() {
+; CHECK-LABEL: define void @test61() {
+; CHECK-NEXT:    [[T:%.*]] = load ptr, ptr @constptr, align 8
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @use_pointer(ptr [[T]])
+; CHECK-NEXT:    ret void
+;
   %t = load ptr, ptr @constptr
   call ptr @llvm.objc.retain(ptr %t)
   call void @callee()
@@ -2342,10 +2950,19 @@ define void @test61() {
 ; Delete a retain matched by releases when one is inside the loop and the
 ; other is outside the loop.
 
-; CHECK-LABEL: define void @test62(
-; CHECK-NOT: @llvm.objc.
-; CHECK: {{^}}}
 define void @test62(ptr %x, ptr %p) nounwind {
+; CHECK-LABEL: define void @test62(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[Q:%.*]] = load i1, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Q]], label %[[LOOP_MORE:.*]], label %[[EXIT:.*]]
+; CHECK:       [[LOOP_MORE]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %loop
 
@@ -2366,13 +2983,21 @@ exit:
 ; Like test62 but with no release in exit.
 ; Don't delete anything!
 
-; CHECK-LABEL: define void @test63(
-; CHECK: loop:
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
-; CHECK: loop.more:
-; CHECK:   call void @llvm.objc.release(ptr %x)
-; CHECK: {{^}}}
 define void @test63(ptr %x, ptr %p) nounwind {
+; CHECK-LABEL: define void @test63(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[Q:%.*]] = load i1, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Q]], label %[[LOOP_MORE:.*]], label %[[EXIT:.*]]
+; CHECK:       [[LOOP_MORE]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %loop
 
@@ -2392,13 +3017,21 @@ exit:
 ; Like test62 but with no release in loop.more.
 ; Don't delete anything!
 
-; CHECK-LABEL: define void @test64(
-; CHECK: loop:
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %x)
-; CHECK: exit:
-; CHECK:   call void @llvm.objc.release(ptr %x)
-; CHECK: {{^}}}
 define void @test64(ptr %x, ptr %p) nounwind {
+; CHECK-LABEL: define void @test64(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[P:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[Q:%.*]] = load i1, ptr [[P]], align 1
+; CHECK-NEXT:    br i1 [[Q]], label %[[LOOP_MORE:.*]], label %[[EXIT:.*]]
+; CHECK:       [[LOOP_MORE]]:
+; CHECK-NEXT:    br label %[[LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %loop
 
@@ -2417,13 +3050,20 @@ exit:
 
 ; Move an autorelease past a phi with a null.
 
-; CHECK-LABEL: define ptr @test65(
-; CHECK: if.then:
-; CHECK:   call ptr @llvm.objc.autorelease(
-; CHECK: return:
-; CHECK-NOT: @llvm.objc.autorelease
-; CHECK: {{^}}}
 define ptr @test65(i1 %x) {
+; CHECK-LABEL: define ptr @test65(
+; CHECK-SAME: i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[X]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[C:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[S:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[C]]) #[[ATTR0]]
+; CHECK-NEXT:    [[Q1:%.*]] = call ptr @llvm.objc.autorelease(ptr [[S]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi ptr [ [[S]], %[[IF_THEN]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT:    ret ptr [[RETVAL]]
+;
 entry:
   br i1 %x, label %return, label %if.then
 
@@ -2440,13 +3080,22 @@ return:                                           ; preds = %if.then, %entry
 
 ; Don't move an autorelease past an autorelease pool boundary.
 
-; CHECK-LABEL: define ptr @test65b(
-; CHECK: if.then:
-; CHECK-NOT: @llvm.objc.autorelease
-; CHECK: return:
-; CHECK:   call ptr @llvm.objc.autorelease(
-; CHECK: {{^}}}
 define ptr @test65b(i1 %x) {
+; CHECK-LABEL: define ptr @test65b(
+; CHECK-SAME: i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[T:%.*]] = call ptr @llvm.objc.autoreleasePoolPush() #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[X]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[C:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[S:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[C]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi ptr [ [[S]], %[[IF_THEN]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT:    call void @llvm.objc.autoreleasePoolPop(ptr [[T]]) #[[ATTR0]]
+; CHECK-NEXT:    [[Q:%.*]] = call ptr @llvm.objc.autorelease(ptr [[RETVAL]]) #[[ATTR0]]
+; CHECK-NEXT:    ret ptr [[RETVAL]]
+;
 entry:
   %t = call ptr @llvm.objc.autoreleasePoolPush()
   br i1 %x, label %return, label %if.then
@@ -2466,13 +3115,20 @@ return:                                           ; preds = %if.then, %entry
 ; Don't move an autoreleaseReuturnValue, which would break
 ; the RV optimization.
 
-; CHECK-LABEL: define ptr @test65c(
-; CHECK: if.then:
-; CHECK-NOT: @llvm.objc.autorelease
-; CHECK: return:
-; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
-; CHECK: {{^}}}
 define ptr @test65c(i1 %x) {
+; CHECK-LABEL: define ptr @test65c(
+; CHECK-SAME: i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[X]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[C:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[S:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[C]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi ptr [ [[S]], %[[IF_THEN]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT:    [[Q:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[RETVAL]]) #[[ATTR0]]
+; CHECK-NEXT:    ret ptr [[RETVAL]]
+;
 entry:
   br i1 %x, label %return, label %if.then
 
@@ -2487,13 +3143,20 @@ return:                                           ; preds = %if.then, %entry
   ret ptr %retval
 }
 
-; CHECK-LABEL: define ptr @test65d(
-; CHECK: if.then:
-; CHECK-NOT: @llvm.objc.autorelease
-; CHECK: return:
-; CHECK:   call ptr @llvm.objc.autoreleaseReturnValue(
-; CHECK: {{^}}}
 define ptr @test65d(i1 %x) {
+; CHECK-LABEL: define ptr @test65d(
+; CHECK-SAME: i1 [[X:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[X]], label %[[RETURN:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[C:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[S:%.*]] = tail call ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue(ptr [[C]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[RETURN]]
+; CHECK:       [[RETURN]]:
+; CHECK-NEXT:    [[RETVAL:%.*]] = phi ptr [ [[S]], %[[IF_THEN]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT:    [[Q:%.*]] = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr [[RETVAL]]) #[[ATTR0]]
+; CHECK-NEXT:    ret ptr [[RETVAL]]
+;
 entry:
   br i1 %x, label %return, label %if.then
 
@@ -2511,13 +3174,22 @@ return:                                           ; preds = %if.then, %entry
 ; An llvm.objc.retain can serve as a may-use for a different pointer.
 ; rdar://11931823
 
-; CHECK-LABEL: define void @test66a(
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
-; CHECK: {{^}}}
 define void @test66a(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
+; CHECK-LABEL: define void @test66a(
+; CHECK-SAME: ptr [[TMP5:%.*]], ptr [[BAR:%.*]], i1 [[TOBOOL:%.*]], i1 [[TOBOOL1:%.*]], ptr [[CALL:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[COND_TRUE:.*]], label %[[COND_END:.*]]
+; CHECK:       [[COND_TRUE]]:
+; CHECK-NEXT:    br label %[[COND_END]]
+; CHECK:       [[COND_END]]:
+; CHECK-NEXT:    [[COND:%.*]] = phi ptr [ [[TMP5]], %[[COND_TRUE]] ], [ [[CALL]], %[[ENTRY]] ]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP8:%.*]] = select i1 [[TOBOOL1]], ptr [[COND]], ptr [[BAR]]
+; CHECK-NEXT:    [[TMP9:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP8]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %tobool, label %cond.true, label %cond.end
 
@@ -2534,13 +3206,22 @@ cond.end:                                         ; preds = %cond.true, %entry
   ret void
 }
 
-; CHECK-LABEL: define void @test66b(
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
-; CHECK: {{^}}}
 define void @test66b(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
+; CHECK-LABEL: define void @test66b(
+; CHECK-SAME: ptr [[TMP5:%.*]], ptr [[BAR:%.*]], i1 [[TOBOOL:%.*]], i1 [[TOBOOL1:%.*]], ptr [[CALL:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[COND_TRUE:.*]], label %[[COND_END:.*]]
+; CHECK:       [[COND_TRUE]]:
+; CHECK-NEXT:    br label %[[COND_END]]
+; CHECK:       [[COND_END]]:
+; CHECK-NEXT:    [[COND:%.*]] = phi ptr [ [[TMP5]], %[[COND_TRUE]] ], [ [[CALL]], %[[ENTRY]] ]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    [[TMP8:%.*]] = select i1 [[TOBOOL1]], ptr [[COND]], ptr [[BAR]]
+; CHECK-NEXT:    [[TMP9:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP8]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %tobool, label %cond.true, label %cond.end
 
@@ -2557,13 +3238,22 @@ cond.end:                                         ; preds = %cond.true, %entry
   ret void
 }
 
-; CHECK-LABEL: define void @test66c(
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
-; CHECK: {{^}}}
 define void @test66c(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
+; CHECK-LABEL: define void @test66c(
+; CHECK-SAME: ptr [[TMP5:%.*]], ptr [[BAR:%.*]], i1 [[TOBOOL:%.*]], i1 [[TOBOOL1:%.*]], ptr [[CALL:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[COND_TRUE:.*]], label %[[COND_END:.*]]
+; CHECK:       [[COND_TRUE]]:
+; CHECK-NEXT:    br label %[[COND_END]]
+; CHECK:       [[COND_END]]:
+; CHECK-NEXT:    [[COND:%.*]] = phi ptr [ [[TMP5]], %[[COND_TRUE]] ], [ [[CALL]], %[[ENTRY]] ]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP8:%.*]] = select i1 [[TOBOOL1]], ptr [[COND]], ptr [[BAR]]
+; CHECK-NEXT:    [[TMP9:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP8]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %tobool, label %cond.true, label %cond.end
 
@@ -2580,13 +3270,22 @@ cond.end:                                         ; preds = %cond.true, %entry
   ret void
 }
 
-; CHECK-LABEL: define void @test66d(
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK:   tail call ptr @llvm.objc.retain(ptr %tmp8) [[NUW]]
-; CHECK:   tail call void @llvm.objc.release(ptr %cond) [[NUW]]
-; CHECK: {{^}}}
 define void @test66d(ptr %tmp5, ptr %bar, i1 %tobool, i1 %tobool1, ptr %call) {
+; CHECK-LABEL: define void @test66d(
+; CHECK-SAME: ptr [[TMP5:%.*]], ptr [[BAR:%.*]], i1 [[TOBOOL:%.*]], i1 [[TOBOOL1:%.*]], ptr [[CALL:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[COND_TRUE:.*]], label %[[COND_END:.*]]
+; CHECK:       [[COND_TRUE]]:
+; CHECK-NEXT:    br label %[[COND_END]]
+; CHECK:       [[COND_END]]:
+; CHECK-NEXT:    [[COND:%.*]] = phi ptr [ [[TMP5]], %[[COND_TRUE]] ], [ [[CALL]], %[[ENTRY]] ]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[COND]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    [[TMP8:%.*]] = select i1 [[TOBOOL1]], ptr [[COND]], ptr [[BAR]]
+; CHECK-NEXT:    [[TMP9:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP8]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   br i1 %tobool, label %cond.true, label %cond.end
 
@@ -2612,11 +3311,6 @@ declare i32 @puts(ptr captures(none)) nounwind
 @str = internal constant [16 x i8] c"-[ Top0 _getX ]\00"
 
 ; FIXME: Should be able to eliminate the retain and release
-; CHECK-LABEL: define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd)
-; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
-; CHECK-NEXT: %call = tail call i32 (ptr, ...) @printf(
-; CHECK: tail call void @llvm.objc.release(ptr %self)
-; CHECK: {{^}}}
 define { <2 x float>, <2 x float> } @"\01-[A z]"(ptr %self, ptr captures(none) %_cmd) nounwind {
 invoke.cont:
   %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
@@ -2654,10 +3348,6 @@ invoke.cont:
 }
 
 ; FIXME: Should be able to eliminate the retain and release
-; CHECK-LABEL: @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd)
-; CHECK: tail call ptr @llvm.objc.retain(ptr %self)
-; CHECK: %puts = tail call i32 @puts
-; CHECK: tail call void @llvm.objc.release(ptr %self)
 define i32 @"\01-[Top0 _getX]"(ptr %self, ptr captures(none) %_cmd) nounwind {
 invoke.cont:
   %i1 = tail call ptr @llvm.objc.retain(ptr %self) nounwind
@@ -2672,14 +3362,24 @@ invoke.cont:
 
 ; A simple loop. Eliminate the retain and release inside of it!
 
-; CHECK: define void @loop(ptr %x, i64 %n) {
-; CHECK: for.body:
-; CHECK-NOT: @llvm.objc.
-; CHECK: @objc_msgSend
-; CHECK-NOT: @llvm.objc.
-; CHECK: for.end:
-; CHECK: {{^}}}
 define void @loop(ptr %x, i64 %n) {
+; CHECK-LABEL: define void @loop(
+; CHECK-SAME: ptr [[X:%.*]], i64 [[N:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CMP9:%.*]] = icmp sgt i64 [[N]], 0
+; CHECK-NEXT:    br i1 [[CMP9]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]]
+; CHECK:       [[FOR_BODY]]:
+; CHECK-NEXT:    [[I_010:%.*]] = phi i64 [ [[INC:%.*]], %[[FOR_BODY]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL:%.*]] = tail call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[X]], ptr [[TMP5]])
+; CHECK-NEXT:    [[INC]] = add nsw i64 [[I_010]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[INC]], [[N]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FOR_END]], label %[[FOR_BODY]]
+; CHECK:       [[FOR_END]]:
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind
   %cmp9 = icmp sgt i64 %n, 0
@@ -2702,9 +3402,6 @@ for.end:                                          ; preds = %for.body, %entry
 
 ; ObjCARCOpt can delete the retain,release on self.
 
-; CHECK: define void @TextEditTest(ptr %self, ptr %pboard) {
-; CHECK-NOT: call ptr @llvm.objc.retain(ptr %tmp7)
-; CHECK: {{^}}}
 
 %0 = type { ptr, ptr }
 %1 = type opaque
@@ -2759,6 +3456,133 @@ for.end:                                          ; preds = %for.body, %entry
 
 declare ptr @truncatedString(ptr, i64)
 define void @TextEditTest(ptr %self, ptr %pboard) {
+; CHECK-LABEL: define void @TextEditTest(
+; CHECK-SAME: ptr [[SELF:%.*]], ptr [[PBOARD:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[ERR:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    store ptr null, ptr [[ERR]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_17", align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @kUTTypePlainText, align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_19", align 8
+; CHECK-NEXT:    [[CALL5:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP1]], ptr [[TMP3]], ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_21", align 8
+; CHECK-NEXT:    [[CALL76:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[PBOARD]], ptr [[TMP5]], ptr [[CALL5]])
+; CHECK-NEXT:    [[TMP9:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL76]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq ptr [[TMP9]], null
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[END:.*]], label %[[LAND_LHS_TRUE:.*]]
+; CHECK:       [[LAND_LHS_TRUE]]:
+; CHECK-NEXT:    [[TMP11:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_23", align 8
+; CHECK-NEXT:    [[CALL137:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[PBOARD]], ptr [[TMP11]], ptr [[TMP9]])
+; CHECK-NEXT:    [[TMP10:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL137]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP12:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL137]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TOBOOL16:%.*]] = icmp eq ptr [[CALL137]], null
+; CHECK-NEXT:    br i1 [[TOBOOL16]], label %[[END]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    [[TMP19:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
+; CHECK-NEXT:    [[CALL21:%.*]] = call signext i8 @objc_msgSend(ptr [[CALL137]], ptr [[TMP19]])
+; CHECK-NEXT:    [[TOBOOL22:%.*]] = icmp eq i8 [[CALL21]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL22]], label %[[IF_THEN44:.*]], label %[[LAND_LHS_TRUE23:.*]]
+; CHECK:       [[LAND_LHS_TRUE23]]:
+; CHECK-NEXT:    [[TMP24:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
+; CHECK-NEXT:    [[TMP26:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
+; CHECK-NEXT:    [[CALL2822:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP24]], ptr [[TMP26]], ptr [[CALL137]])
+; CHECK-NEXT:    [[TMP14:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL2822]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TOBOOL30:%.*]] = icmp eq ptr [[CALL2822]], null
+; CHECK-NEXT:    br i1 [[TOBOOL30]], label %[[IF_THEN44]], label %[[IF_END:.*]]
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    [[TMP32:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
+; CHECK-NEXT:    [[TMP33:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
+; CHECK-NEXT:    [[CALL35:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP32]], ptr [[TMP33]])
+; CHECK-NEXT:    [[TMP37:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
+; CHECK-NEXT:    [[CALL3923:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL35]], ptr [[TMP37]], ptr [[CALL2822]], i32 signext 1, ptr [[ERR]])
+; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[CALL3923]], null
+; CHECK-NEXT:    br i1 [[CMP]], label %[[IF_THEN44]], label %[[END]]
+; CHECK:       [[IF_THEN44]]:
+; CHECK-NEXT:    [[URL_025:%.*]] = phi ptr [ [[CALL2822]], %[[IF_END]] ], [ [[CALL2822]], %[[LAND_LHS_TRUE23]] ], [ null, %[[IF_THEN]] ]
+; CHECK-NEXT:    [[TMP49:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_35", align 8
+; CHECK-NEXT:    [[CALL51:%.*]] = call [[STRUCT__NSRANGE:%.*]] @[[OBJC_MSGSEND:[a-zA-Z0-9_$\"\\.-]*[a-zA-Z_$\"\\.-][a-zA-Z0-9_$\"\\.-]*]](ptr [[CALL137]], ptr [[TMP49]], i64 0, i64 0)
+; CHECK-NEXT:    [[CALL513:%.*]] = extractvalue [[STRUCT__NSRANGE]] [[CALL51]], 0
+; CHECK-NEXT:    [[CALL514:%.*]] = extractvalue [[STRUCT__NSRANGE]] [[CALL51]], 1
+; CHECK-NEXT:    [[TMP52:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_37", align 8
+; CHECK-NEXT:    [[CALL548:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL137]], ptr [[TMP52]], i64 [[CALL513]], i64 [[CALL514]])
+; CHECK-NEXT:    [[TMP55:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_38", align 8
+; CHECK-NEXT:    [[TMP56:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_40", align 8
+; CHECK-NEXT:    [[CALL58:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP55]], ptr [[TMP56]])
+; CHECK-NEXT:    [[TMP59:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_42", align 8
+; CHECK-NEXT:    [[CALL6110:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL548]], ptr [[TMP59]], ptr [[CALL58]])
+; CHECK-NEXT:    [[TMP15:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL6110]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL137]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP64:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_46", align 8
+; CHECK-NEXT:    [[CALL66:%.*]] = call signext i8 @objc_msgSend(ptr [[CALL6110]], ptr [[TMP64]], ptr @_unnamed_cfstring_44)
+; CHECK-NEXT:    [[TOBOOL67:%.*]] = icmp eq i8 [[CALL66]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL67]], label %[[IF_END74:.*]], label %[[IF_THEN68:.*]]
+; CHECK:       [[IF_THEN68]]:
+; CHECK-NEXT:    [[TMP70:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_48", align 8
+; CHECK-NEXT:    [[CALL7220:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL6110]], ptr [[TMP70]])
+; CHECK-NEXT:    [[TMP16:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL7220]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL6110]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[IF_END74]]
+; CHECK:       [[IF_END74]]:
+; CHECK-NEXT:    [[FILENAME_0_IN:%.*]] = phi ptr [ [[CALL7220]], %[[IF_THEN68]] ], [ [[CALL6110]], %[[IF_THEN44]] ]
+; CHECK-NEXT:    [[TMP17:%.*]] = load ptr, ptr @"\01l_objc_msgSend_fixup_isEqual_", align 16
+; CHECK-NEXT:    [[CALL78:%.*]] = call signext i8 (ptr, ptr, ptr, ...) [[TMP17]](ptr [[CALL137]], ptr @"\01l_objc_msgSend_fixup_isEqual_", ptr [[FILENAME_0_IN]])
+; CHECK-NEXT:    [[TOBOOL79:%.*]] = icmp eq i8 [[CALL78]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL79]], label %[[LAND_LHS_TRUE80:.*]], label %[[IF_THEN109:.*]]
+; CHECK:       [[LAND_LHS_TRUE80]]:
+; CHECK-NEXT:    [[TMP82:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_25", align 8
+; CHECK-NEXT:    [[CALL84:%.*]] = call signext i8 @objc_msgSend(ptr [[FILENAME_0_IN]], ptr [[TMP82]])
+; CHECK-NEXT:    [[TOBOOL86:%.*]] = icmp eq i8 [[CALL84]], 0
+; CHECK-NEXT:    br i1 [[TOBOOL86]], label %[[IF_THEN109]], label %[[IF_END106:.*]]
+; CHECK:       [[IF_END106]]:
+; CHECK-NEXT:    [[TMP88:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_26", align 8
+; CHECK-NEXT:    [[TMP90:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_28", align 8
+; CHECK-NEXT:    [[CALL9218:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP88]], ptr [[TMP90]], ptr [[FILENAME_0_IN]])
+; CHECK-NEXT:    [[TMP21:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL9218]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[URL_025]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP94:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_29", align 8
+; CHECK-NEXT:    [[TMP95:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_31", align 8
+; CHECK-NEXT:    [[CALL97:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP94]], ptr [[TMP95]])
+; CHECK-NEXT:    [[TMP99:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_33", align 8
+; CHECK-NEXT:    [[CALL10119:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL97]], ptr [[TMP99]], ptr [[CALL9218]], i32 signext 1, ptr [[ERR]])
+; CHECK-NEXT:    [[PHITMP:%.*]] = icmp eq ptr [[CALL10119]], null
+; CHECK-NEXT:    br i1 [[PHITMP]], label %[[IF_THEN109]], label %[[END]]
+; CHECK:       [[IF_THEN109]]:
+; CHECK-NEXT:    [[URL_129:%.*]] = phi ptr [ [[CALL9218]], %[[IF_END106]] ], [ [[URL_025]], %[[IF_END74]] ], [ [[URL_025]], %[[LAND_LHS_TRUE80]] ]
+; CHECK-NEXT:    [[TMP110:%.*]] = load ptr, ptr [[ERR]], align 8
+; CHECK-NEXT:    [[TOBOOL111:%.*]] = icmp eq ptr [[TMP110]], null
+; CHECK-NEXT:    br i1 [[TOBOOL111]], label %[[IF_THEN112:.*]], label %[[IF_END125:.*]]
+; CHECK:       [[IF_THEN112]]:
+; CHECK-NEXT:    [[TMP113:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_50", align 8
+; CHECK-NEXT:    [[TMP114:%.*]] = load ptr, ptr @NSCocoaErrorDomain, align 8
+; CHECK-NEXT:    [[TMP115:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_51", align 8
+; CHECK-NEXT:    [[CALL117:%.*]] = call ptr @truncatedString(ptr [[FILENAME_0_IN]], i64 1034)
+; CHECK-NEXT:    [[TMP118:%.*]] = load ptr, ptr @NSFilePathErrorKey, align 8
+; CHECK-NEXT:    [[TMP119:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_53", align 8
+; CHECK-NEXT:    [[CALL12113:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP115]], ptr [[TMP119]], ptr [[CALL117]], ptr [[TMP118]], ptr null)
+; CHECK-NEXT:    [[TMP122:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_55", align 8
+; CHECK-NEXT:    [[CALL12414:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP113]], ptr [[TMP122]], ptr [[TMP114]], i64 258, ptr [[CALL12113]])
+; CHECK-NEXT:    [[TMP23:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL12414]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP25:%.*]] = call ptr @llvm.objc.autorelease(ptr [[TMP23]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[TMP25]], ptr [[ERR]], align 8
+; CHECK-NEXT:    br label %[[IF_END125]]
+; CHECK:       [[IF_END125]]:
+; CHECK-NEXT:    [[TMP127:%.*]] = phi ptr [ [[TMP110]], %[[IF_THEN109]] ], [ [[TMP25]], %[[IF_THEN112]] ]
+; CHECK-NEXT:    [[TMP126:%.*]] = load ptr, ptr @"\01L_OBJC_CLASSLIST_REFERENCES_$_56", align 8
+; CHECK-NEXT:    [[TMP128:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_58", align 8
+; CHECK-NEXT:    [[CALL13015:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[TMP126]], ptr [[TMP128]], ptr [[TMP127]])
+; CHECK-NEXT:    [[TMP131:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_60", align 8
+; CHECK-NEXT:    [[CALL13317:%.*]] = call ptr (ptr, ptr, ...) @objc_msgSend(ptr [[CALL13015]], ptr [[TMP131]])
+; CHECK-NEXT:    br label %[[END]]
+; CHECK:       [[END]]:
+; CHECK-NEXT:    [[FILENAME_2:%.*]] = phi ptr [ [[FILENAME_0_IN]], %[[IF_END106]] ], [ [[FILENAME_0_IN]], %[[IF_END125]] ], [ [[CALL137]], %[[LAND_LHS_TRUE]] ], [ null, %[[ENTRY]] ], [ [[CALL137]], %[[IF_END]] ]
+; CHECK-NEXT:    [[ORIGFILENAME_0:%.*]] = phi ptr [ [[CALL137]], %[[IF_END106]] ], [ [[CALL137]], %[[IF_END125]] ], [ [[CALL137]], %[[LAND_LHS_TRUE]] ], [ null, %[[ENTRY]] ], [ [[CALL137]], %[[IF_END]] ]
+; CHECK-NEXT:    [[URL_2:%.*]] = phi ptr [ [[CALL9218]], %[[IF_END106]] ], [ [[URL_129]], %[[IF_END125]] ], [ null, %[[LAND_LHS_TRUE]] ], [ null, %[[ENTRY]] ], [ [[CALL2822]], %[[IF_END]] ]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP9]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[URL_2]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[ORIGFILENAME_0]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[FILENAME_2]]) #[[ATTR0]], !clang.imprecise_release [[META3]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %err = alloca ptr, align 8
   %tmp8 = call ptr @llvm.objc.retain(ptr %self) nounwind
@@ -2911,12 +3735,13 @@ declare i32 @llvm.objc.sync.exit(ptr)
 ; Make sure that we understand that objc_sync_{enter,exit} are IC_User not
 ; IC_Call/IC_CallOrUser.
 
-; CHECK-LABEL:      define void @test67(
-; CHECK-NEXT:   call i32 @llvm.objc.sync.enter(ptr %x)
-; CHECK-NEXT:   call i32 @llvm.objc.sync.exit(ptr %x)
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test67(ptr %x) {
+; CHECK-LABEL: define void @test67(
+; CHECK-SAME: ptr [[X:%.*]]) {
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.objc.sync.enter(ptr [[X]])
+; CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.objc.sync.exit(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %x)
   call i32 @llvm.objc.sync.enter(ptr %x)
   call i32 @llvm.objc.sync.exit(ptr %x)
@@ -2924,13 +3749,13 @@ define void @test67(ptr %x) {
   ret void
 }
 
-; CHECK-LABEL: define void @test68(
-; CHECK-NOT:     call
-; CHECK:         call void @callee2(
-; CHECK-NOT:     call
-; CHECK:         ret void
 
 define void @test68(ptr %a, ptr %b) {
+; CHECK-LABEL: define void @test68(
+; CHECK-SAME: ptr [[A:%.*]], ptr [[B:%.*]]) {
+; CHECK-NEXT:    call void @callee2(ptr [[A]], ptr [[B]])
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %a)
   call ptr @llvm.objc.retain(ptr %b)
   call void @callee2(ptr %a, ptr %b)
@@ -2946,11 +3771,12 @@ define void @test68(ptr %a, ptr %b) {
 !1 = !{i32 1, !"Debug Info Version", i32 3}
 !2 = distinct !DISubprogram(unit: !3)
 !3 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang",
-                             file: !4,
-                             isOptimized: true, flags: "-O2",
-                             splitDebugFilename: "abc.debug", emissionKind: 2)
+  file: !4,
+  isOptimized: true, flags: "-O2",
+  splitDebugFilename: "abc.debug", emissionKind: 2)
 !4 = !DIFile(filename: "path/to/file", directory: "/path/to/dir")
 !5 = !{i32 2, !"Debug Info Version", i32 3}
 
-; CHECK: attributes [[NUW]] = { nounwind }
-; CHECK: ![[RELEASE]] = !{}
+;.
+; CHECK: [[META3]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/clang-arc-use-barrier.ll b/llvm/test/Transforms/ObjCARC/clang-arc-use-barrier.ll
index 2581917a3896b..2bfdd49e35157 100644
--- a/llvm/test/Transforms/ObjCARC/clang-arc-use-barrier.ll
+++ b/llvm/test/Transforms/ObjCARC/clang-arc-use-barrier.ll
@@ -1,15 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=objc-arc -S %s | FileCheck %s
 
 %0 = type opaque
 
 ; Make sure ARC optimizer doesn't sink @obj_retain past @llvm.objc.clang.arc.use.
 
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void (...) @llvm.objc.clang.arc.use(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: call void (...) @llvm.objc.clang.arc.use(
 
 define void @runTest() local_unnamed_addr {
+; CHECK-LABEL: define void @runTest() local_unnamed_addr {
+; CHECK-NEXT:    [[TMP1:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = tail call ptr @foo0()
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[TMP3]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    store ptr [[TMP3]], ptr [[TMP1]], align 8
+; CHECK-NEXT:    call void @foo1(ptr nonnull [[TMP1]])
+; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP5]]) #[[ATTR0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[TMP3]])
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP3]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[TMP5]], ptr [[TMP2]], align 8
+; CHECK-NEXT:    call void @foo1(ptr nonnull [[TMP2]])
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[TMP2]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP6]]) #[[ATTR0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[TMP5]])
+; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[TMP2]], align 8
+; CHECK-NEXT:    [[TMP7:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP5]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @foo2(ptr [[TMP6]])
+; CHECK-NEXT:    [[TMP8:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP6]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %1 = alloca ptr, align 8
   %2 = alloca ptr, align 8
   %3 = tail call ptr @foo0()
diff --git a/llvm/test/Transforms/ObjCARC/code-motion.ll b/llvm/test/Transforms/ObjCARC/code-motion.ll
index 499ee77bc6541..849d4ca163771 100644
--- a/llvm/test/Transforms/ObjCARC/code-motion.ll
+++ b/llvm/test/Transforms/ObjCARC/code-motion.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
 
 declare void @alterRefCount()
@@ -9,10 +10,18 @@ declare void @readOnlyFunc(ptr, ptr)
 ; Check that ARC optimizer doesn't reverse the order of the retain call and the
 ; release call when there are debug instructions.
 
-; CHECK: call ptr @llvm.objc.retain(ptr %x)
-; CHECK: call void @llvm.objc.release(ptr %x)
 
 define i32 @test(ptr %x, ptr %y, i8 %z, i32 %i) {
+; CHECK-LABEL: define i32 @test(
+; CHECK-SAME: ptr [[X:%.*]], ptr [[Y:%.*]], i8 [[Z:%.*]], i32 [[I:%.*]]) {
+; CHECK-NEXT:    [[I_ADDR:%.*]] = alloca i32, align 4
+; CHECK-NEXT:    store i32 [[I]], ptr [[I_ADDR]], align 4
+; CHECK-NEXT:    store i8 [[Z]], ptr [[X]], align 1
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[X]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    call void @alterRefCount()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret i32 [[I]]
+;
   %i.addr = alloca i32, align 4
   store i32 %i, ptr %i.addr, align 4
   %v1 = tail call ptr @llvm.objc.retain(ptr %x)
@@ -26,11 +35,16 @@ define i32 @test(ptr %x, ptr %y, i8 %z, i32 %i) {
 ; ARC optimizer shouldn't move the release call, which is a precise release call
 ; past the call to @alterRefCount.
 
-; CHECK-LABEL: define void @test2(
-; CHECK: call void @alterRefCount(
-; CHECK: call void @llvm.objc.release(
 
 define void @test2() {
+; CHECK-LABEL: define void @test2() {
+; CHECK-NEXT:    [[V0:%.*]] = load ptr, ptr @g0, align 8
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[V0]]) #[[ATTR0]]
+; CHECK-NEXT:    tail call void @use(ptr [[V0]])
+; CHECK-NEXT:    tail call void @alterRefCount()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[V0]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
   %v0 = load ptr, ptr @g0, align 8
   %v1 = tail call ptr @llvm.objc.retain(ptr %v0)
   tail call void @use(ptr %v0)
@@ -51,20 +65,21 @@ define void @test2() {
 ; Ideally, the retain/release pairs in BB if.then should be removed.
 
 define void @test3(ptr %obj, i1 %cond) {
-; CHECK-LABEL: @test3(
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ:%.*]])
-; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ]], ptr null)
+; CHECK-LABEL: define void @test3(
+; CHECK-SAME: ptr [[OBJ:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ]], ptr null) #[[ATTR1:[0-9]+]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 1, 2
 ; CHECK-NEXT:    call void @alterRefCount()
-; CHECK-NEXT:    br label [[JOIN:%.*]]
-; CHECK:       if.else:
+; CHECK-NEXT:    br label %[[JOIN:.*]]
+; CHECK:       [[IF_ELSE]]:
 ; CHECK-NEXT:    call void @alterRefCount()
 ; CHECK-NEXT:    call void @use(ptr [[OBJ]])
-; CHECK-NEXT:    br label [[JOIN]]
-; CHECK:       join:
-; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ]]) {{.*}}, !clang.imprecise_release !2
+; CHECK-NEXT:    br label %[[JOIN]]
+; CHECK:       [[JOIN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ]]) #[[ATTR0]], !clang.imprecise_release [[META2:![0-9]+]]
 ; CHECK-NEXT:    ret void
 ;
   %v0 = call ptr @llvm.objc.retain(ptr %obj)
@@ -87,23 +102,24 @@ join:
 }
 
 define void @test4(ptr %obj0, ptr %obj1, i1 %cond) {
-; CHECK-LABEL: @test4(
-; CHECK-NEXT:    [[TMP3:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ0:%.*]])
-; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ1:%.*]])
-; CHECK-NEXT:    br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ0]], ptr [[OBJ1]])
+; CHECK-LABEL: define void @test4(
+; CHECK-SAME: ptr [[OBJ0:%.*]], ptr [[OBJ1:%.*]], i1 [[COND:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[V1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ1]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ0]], ptr [[OBJ1]]) #[[ATTR1]]
 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 1, 2
 ; CHECK-NEXT:    call void @alterRefCount()
-; CHECK-NEXT:    br label [[JOIN:%.*]]
-; CHECK:       if.else:
+; CHECK-NEXT:    br label %[[JOIN:.*]]
+; CHECK:       [[IF_ELSE]]:
 ; CHECK-NEXT:    call void @alterRefCount()
 ; CHECK-NEXT:    call void @use(ptr [[OBJ0]])
 ; CHECK-NEXT:    call void @use(ptr [[OBJ1]])
-; CHECK-NEXT:    br label [[JOIN]]
-; CHECK:       join:
-; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ0]]) {{.*}}, !clang.imprecise_release !2
-; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ1]]) {{.*}}, !clang.imprecise_release !2
+; CHECK-NEXT:    br label %[[JOIN]]
+; CHECK:       [[JOIN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ0]]) #[[ATTR0]], !clang.imprecise_release [[META2]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ1]]) #[[ATTR0]], !clang.imprecise_release [[META2]]
 ; CHECK-NEXT:    ret void
 ;
   %v0 = call ptr @llvm.objc.retain(ptr %obj0)
@@ -132,26 +148,27 @@ join:
 ; eliminated are in different blocks (bb1 and if.then).
 
 define void @test5(ptr %obj, i1 %cond0, i1 %cond1) {
-; CHECK-LABEL: @test5(
-; CHECK-NEXT:    [[V0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ:%.*]])
-; CHECK-NEXT:    br i1 [[COND0:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
-; CHECK:       if.then:
-; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ]], ptr null)
-; CHECK-NEXT:    br i1 [[COND1:%.*]], label [[IF_THEN2:%.*]], label [[IF_ELSE2:%.*]]
-; CHECK:       if.then2:
-; CHECK-NEXT:    br label [[BB1:%.*]]
-; CHECK:       if.else2:
-; CHECK-NEXT:    br label [[BB1]]
-; CHECK:       bb1:
+; CHECK-LABEL: define void @test5(
+; CHECK-SAME: ptr [[OBJ:%.*]], i1 [[COND0:%.*]], i1 [[COND1:%.*]]) {
+; CHECK-NEXT:    [[V0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[OBJ]]) #[[ATTR0]]
+; CHECK-NEXT:    br i1 [[COND0]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    call void @readOnlyFunc(ptr [[OBJ]], ptr null) #[[ATTR1]]
+; CHECK-NEXT:    br i1 [[COND1]], label %[[IF_THEN2:.*]], label %[[IF_ELSE2:.*]]
+; CHECK:       [[IF_THEN2]]:
+; CHECK-NEXT:    br label %[[BB1:.*]]
+; CHECK:       [[IF_ELSE2]]:
+; CHECK-NEXT:    br label %[[BB1]]
+; CHECK:       [[BB1]]:
 ; CHECK-NEXT:    [[TMP1:%.*]] = add i32 1, 2
 ; CHECK-NEXT:    call void @alterRefCount()
-; CHECK-NEXT:    br label [[JOIN:%.*]]
-; CHECK:       if.else:
+; CHECK-NEXT:    br label %[[JOIN:.*]]
+; CHECK:       [[IF_ELSE]]:
 ; CHECK-NEXT:    call void @alterRefCount()
 ; CHECK-NEXT:    call void @use(ptr [[OBJ]])
-; CHECK-NEXT:    br label [[JOIN]]
-; CHECK:       join:
-; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ]])
+; CHECK-NEXT:    br label %[[JOIN]]
+; CHECK:       [[JOIN]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[OBJ]]) #[[ATTR0]], !clang.imprecise_release [[META2]]
 ; CHECK-NEXT:    ret void
 ;
   %v0 = call ptr @llvm.objc.retain(ptr %obj)
@@ -201,3 +218,6 @@ attributes #0 = { readonly }
 !8 = distinct !DICompileUnit(language: DW_LANG_ObjC, file: !4, isOptimized: false, runtimeVersion: 2, emissionKind: FullDebug, enums: !9, nameTableKind: None)
 !9 = !{}
 !10 = !DILocation(line: 1, column: 14, scope: !3)
+;.
+; CHECK: [[META2]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/funclet-catchpad.ll b/llvm/test/Transforms/ObjCARC/funclet-catchpad.ll
index 9f047c29bc159..78e75da5837b2 100644
--- a/llvm/test/Transforms/ObjCARC/funclet-catchpad.ll
+++ b/llvm/test/Transforms/ObjCARC/funclet-catchpad.ll
@@ -1,14 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -mtriple=x86_64-windows-msvc -passes=objc-arc -S < %s | FileCheck %s
 
-; Check that funclet tokens are preserved
-;
-; CHECK-LABEL:  catch:
-; CHECK:          %1 = catchpad within %0
-; CHECK:          %2 = tail call ptr @llvm.objc.retain(ptr %exn) #0 [ "funclet"(token %1) ]
-; CHECK:          call void @llvm.objc.release(ptr %exn) #0 [ "funclet"(token %1) ]
-; CHECK:          catchret from %1 to label %eh.cont
+; Check that funclet tokens are preserved, and that the optimization correctly
+; reorders retain and release calls while preserving the funclet operand.
 
 define void @try_catch_with_objc_intrinsic() personality ptr @__CxxFrameHandler3 {
+; CHECK-LABEL: @try_catch_with_objc_intrinsic(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[EXN_SLOT:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    invoke void @may_throw(ptr null)
+; CHECK-NEXT:            to label %eh.cont unwind label %catch.dispatch
+; CHECK:       catch.dispatch:
+; CHECK-NEXT:    [[TMP0:%.*]] = catchswitch within none [label %catch] unwind to caller
+; CHECK:       eh.cont:
+; CHECK-NEXT:    ret void
+; CHECK:       catch:
+; CHECK-NEXT:    [[TMP1:%.*]] = catchpad within [[TMP0]] [ptr null, i32 0, ptr [[EXN_SLOT]]]
+; CHECK-NEXT:    br label %if.then
+; CHECK:       if.then:
+; CHECK-NEXT:    [[EXN:%.*]] = load ptr, ptr null, align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[EXN]]) #[[ATTR0:[0-9]+]] [ "funclet"(token [[TMP1]]) ]
+; CHECK-NEXT:    call void @may_throw(ptr [[EXN]])
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[EXN]]) #[[ATTR0]] [ "funclet"(token [[TMP1]]) ]
+; CHECK-NEXT:    catchret from [[TMP1]] to label %eh.cont
+;
 entry:
   %exn.slot = alloca ptr, align 8
   invoke void @may_throw(ptr null) to label %eh.cont unwind label %catch.dispatch
diff --git a/llvm/test/Transforms/ObjCARC/intrinsic-use.ll b/llvm/test/Transforms/ObjCARC/intrinsic-use.ll
index 884e2ebea7350..404a7877d0896 100644
--- a/llvm/test/Transforms/ObjCARC/intrinsic-use.ll
+++ b/llvm/test/Transforms/ObjCARC/intrinsic-use.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
 
 target datalayout = "e-p:64:64:64"
@@ -16,29 +17,33 @@ declare void @can_release(ptr)
 ; Ensure that we honor clang.arc.use as a use and don't miscompile
 ; the reduced test case from <rdar://13195034>.
 ;
-; CHECK-LABEL:      define void @test0(
-; CHECK:        @llvm.objc.retain(ptr %x)
-; CHECK-NEXT:   store ptr %y, ptr %temp0
-; CHECK-NEXT:   @llvm.objc.retain(ptr %y)
-; CHECK-NEXT:   call void @test0_helper
-; CHECK-NEXT:   [[VAL1:%.*]] = load ptr, ptr %temp0
-; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL1]])
-; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr %y)
-; CHECK-NEXT:   @llvm.objc.release(ptr %y)
-; CHECK-NEXT:   store ptr [[VAL1]], ptr %temp1
-; CHECK-NEXT:   call void @test0_helper
-; CHECK-NEXT:   [[VAL2:%.*]] = load ptr, ptr %temp1
-; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL2]])
-; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])
-; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL1]])
-; CHECK-NEXT:   @llvm.objc.autorelease(ptr %x)
-; CHECK-NEXT:   store ptr %x, ptr %out
-; CHECK-NEXT:   @llvm.objc.retain(ptr %x)
-; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL2]])
-; CHECK-NEXT:   @llvm.objc.release(ptr %x)
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test0(ptr %out, ptr %x, ptr %y) {
+; CHECK-LABEL: define void @test0(
+; CHECK-SAME: ptr [[OUT:%.*]], ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TEMP0:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TEMP1:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    store ptr [[Y]], ptr [[TEMP0]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @test0_helper(ptr [[X]], ptr [[TEMP0]])
+; CHECK-NEXT:    [[VAL1:%.*]] = load ptr, ptr [[TEMP0]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[VAL1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[VAL1]], ptr [[TEMP1]], align 8
+; CHECK-NEXT:    call void @test0_helper(ptr [[X]], ptr [[TEMP1]])
+; CHECK-NEXT:    [[VAL2:%.*]] = load ptr, ptr [[TEMP1]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[VAL2]]) #[[ATTR0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[OUT]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL2]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP5:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %temp0 = alloca ptr, align 8
   %temp1 = alloca ptr, align 8
@@ -64,27 +69,31 @@ entry:
   ret void
 }
 
-; CHECK-LABEL:      define void @test0a(
-; CHECK:        @llvm.objc.retain(ptr %x)
-; CHECK-NEXT:   store ptr %y, ptr %temp0
-; CHECK-NEXT:   @llvm.objc.retain(ptr %y)
-; CHECK-NEXT:   call void @test0_helper
-; CHECK-NEXT:   [[VAL1:%.*]] = load ptr, ptr %temp0
-; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL1]])
-; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr %y)
-; CHECK-NEXT:   @llvm.objc.release(ptr %y)
-; CHECK-NEXT:   store ptr [[VAL1]], ptr %temp1
-; CHECK-NEXT:   call void @test0_helper
-; CHECK-NEXT:   [[VAL2:%.*]] = load ptr, ptr %temp1
-; CHECK-NEXT:   @llvm.objc.retain(ptr [[VAL2]])
-; CHECK-NEXT:   call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]])
-; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL1]])
-; CHECK-NEXT:   @llvm.objc.autorelease(ptr %x)
-; CHECK-NEXT:   @llvm.objc.release(ptr [[VAL2]])
-; CHECK-NEXT:   store ptr %x, ptr %out
-; CHECK-NEXT:   ret void
-; CHECK-NEXT: }
 define void @test0a(ptr %out, ptr %x, ptr %y) {
+; CHECK-LABEL: define void @test0a(
+; CHECK-SAME: ptr [[OUT:%.*]], ptr [[X:%.*]], ptr [[Y:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TEMP0:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TEMP1:%.*]] = alloca ptr, align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[Y]], ptr [[TEMP0]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[Y]]) #[[ATTR0]], !clang.imprecise_release [[META0:![0-9]+]]
+; CHECK-NEXT:    call void @test0_helper(ptr [[X]], ptr [[TEMP0]])
+; CHECK-NEXT:    [[VAL1:%.*]] = load ptr, ptr [[TEMP0]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[VAL1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[Y]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[VAL1]], ptr [[TEMP1]], align 8
+; CHECK-NEXT:    call void @test0_helper(ptr [[X]], ptr [[TEMP1]])
+; CHECK-NEXT:    [[VAL2:%.*]] = load ptr, ptr [[TEMP1]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[VAL2]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.use(ptr [[VAL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL1]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = call ptr @llvm.objc.autorelease(ptr [[X]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP4:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL2]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[X]], ptr [[OUT]], align 8
+; CHECK-NEXT:    ret void
+;
 entry:
   %temp0 = alloca ptr, align 8
   %temp1 = alloca ptr, align 8
@@ -113,12 +122,14 @@ entry:
 ; ARC optimizer should be able to safely remove the retain/release pair as the
 ; call to @llvm.objc.clang.arc.noop.use is a no-op.
 
-; CHECK-LABEL: define void @test_arc_noop_use(
-; CHECK-NEXT:    call void @can_release(ptr %x)
-; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use(
-; CHECK-NEXT:    ret void
 
 define void @test_arc_noop_use(ptr %out, ptr %x) {
+; CHECK-LABEL: define void @test_arc_noop_use(
+; CHECK-SAME: ptr [[OUT:%.*]], ptr [[X:%.*]]) {
+; CHECK-NEXT:    call void @can_release(ptr [[X]])
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use(ptr [[X]])
+; CHECK-NEXT:    ret void
+;
   call ptr @llvm.objc.retain(ptr %x)
   call void @can_release(ptr %x)
   call void (...) @llvm.objc.clang.arc.noop.use(ptr %x)
@@ -128,3 +139,6 @@ define void @test_arc_noop_use(ptr %out, ptr %x) {
 
 !0 = !{}
 
+;.
+; CHECK: [[META0]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/invoke.ll b/llvm/test/Transforms/ObjCARC/invoke.ll
index a792b8e868366..7c1a454daab2c 100644
--- a/llvm/test/Transforms/ObjCARC/invoke.ll
+++ b/llvm/test/Transforms/ObjCARC/invoke.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -S -passes=objc-arc < %s | FileCheck %s
 
 declare ptr @llvm.objc.retain(ptr)
@@ -10,20 +11,28 @@ declare ptr @returner()
 
 ; ARCOpt shouldn't try to move the releases to the block containing the invoke.
 
-; CHECK-LABEL: define void @test0(
-; CHECK: invoke.cont:
-; CHECK:   call void @llvm.objc.release(ptr %zipFile) [[NUW:#[0-9]+]], !clang.imprecise_release !0
-; CHECK:   ret void
-; CHECK: lpad:
-; CHECK:   call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !0
-; CHECK:   ret void
-; CHECK-NEXT: }
 define void @test0(ptr %zipFile) personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: define void @test0(
+; CHECK-SAME: ptr [[ZIPFILE:%.*]]) personality ptr @__gxx_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[ZIPFILE]]) #[[ATTR0:[0-9]+]], !clang.imprecise_release [[META0:![0-9]+]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[ZIPFILE]])
+; CHECK-NEXT:    invoke void @objc_msgSend(ptr [[ZIPFILE]])
+; CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+; CHECK:       [[INVOKE_CONT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[ZIPFILE]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[EXN:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[ZIPFILE]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %zipFile) nounwind
   call void @use_pointer(ptr %zipFile)
-  invoke void @objc_msgSend(ptr %zipFile) 
-          to label %invoke.cont unwind label %lpad
+  invoke void @objc_msgSend(ptr %zipFile)
+  to label %invoke.cont unwind label %lpad
 
 invoke.cont:                                      ; preds = %entry
   call void @llvm.objc.release(ptr %zipFile) nounwind, !clang.imprecise_release !0
@@ -31,31 +40,39 @@ invoke.cont:                                      ; preds = %entry
 
 lpad:                                             ; preds = %entry
   %exn = landingpad {ptr, i32}
-           cleanup
+  cleanup
   call void @llvm.objc.release(ptr %zipFile) nounwind, !clang.imprecise_release !0
   ret void
 }
 
 ; ARCOpt should move the release before the callee calls.
 
-; CHECK-LABEL: define void @test1(
-; CHECK: invoke.cont:
-; CHECK:   call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !0
-; CHECK:   call void @callee()
-; CHECK:   br label %done
-; CHECK: lpad:
-; CHECK:   call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !0
-; CHECK:   call void @callee()
-; CHECK:   br label %done
-; CHECK: done:
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test1(ptr %zipFile) personality ptr @__gxx_personality_v0 {
+; CHECK-LABEL: define void @test1(
+; CHECK-SAME: ptr [[ZIPFILE:%.*]]) personality ptr @__gxx_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[ZIPFILE]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[ZIPFILE]])
+; CHECK-NEXT:    invoke void @objc_msgSend(ptr [[ZIPFILE]])
+; CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]]
+; CHECK:       [[INVOKE_CONT]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[ZIPFILE]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[DONE:.*]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[EXN:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[ZIPFILE]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[DONE]]
+; CHECK:       [[DONE]]:
+; CHECK-NEXT:    ret void
+;
 entry:
   call ptr @llvm.objc.retain(ptr %zipFile) nounwind
   call void @use_pointer(ptr %zipFile)
   invoke void @objc_msgSend(ptr %zipFile)
-          to label %invoke.cont unwind label %lpad
+  to label %invoke.cont unwind label %lpad
 
 invoke.cont:                                      ; preds = %entry
   call void @callee()
@@ -63,7 +80,7 @@ invoke.cont:                                      ; preds = %entry
 
 lpad:                                             ; preds = %entry
   %exn = landingpad {ptr, i32}
-           cleanup
+  cleanup
   call void @callee()
   br label %done
 
@@ -75,26 +92,33 @@ done:
 ; The optimizer should ignore invoke unwind paths consistently.
 ; PR12265
 
-; CHECK: define void @test2() personality ptr @__objc_personality_v0 {
-; CHECK: invoke.cont:
-; CHECK-NEXT: call ptr @llvm.objc.retain
-; CHECK-NOT: @llvm.objc.r
-; CHECK: finally.cont:
-; CHECK-NEXT: call void @llvm.objc.release
-; CHECK-NOT: @objc
-; CHECK: finally.rethrow:
-; CHECK-NOT: @objc
-; CHECK: }
 define void @test2() personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test2() personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[CALL:%.*]] = invoke ptr @objc_msgSend()
+; CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label %[[FINALLY_RETHROW:.*]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[INVOKE_CONT]]:
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @objc_msgSend(), !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK-NEXT:    invoke void @use_pointer(ptr [[CALL]])
+; CHECK-NEXT:            to label %[[FINALLY_CONT:.*]] unwind label %[[FINALLY_RETHROW]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[FINALLY_CONT]]:
+; CHECK-NEXT:    tail call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[FINALLY_RETHROW]]:
+; CHECK-NEXT:    [[TMP2:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            catch ptr null
+; CHECK-NEXT:    unreachable
+;
 entry:
   %call = invoke ptr @objc_msgSend()
-          to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
+  to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
 
 invoke.cont:                                      ; preds = %entry
   %tmp1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind
   call void @objc_msgSend(), !clang.arc.no_objc_arc_exceptions !0
   invoke void @use_pointer(ptr %call)
-          to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
+  to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !0
 
 finally.cont:                                     ; preds = %invoke.cont
   tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0
@@ -102,18 +126,33 @@ finally.cont:                                     ; preds = %invoke.cont
 
 finally.rethrow:                                  ; preds = %invoke.cont, %entry
   %tmp2 = landingpad { ptr, i32 }
-          catch ptr null
+  catch ptr null
   unreachable
 }
 
 ; Don't try to place code on invoke critical edges.
 
-; CHECK-LABEL: define void @test3(
-; CHECK: if.end:
-; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test3(ptr %p, i1 %b) personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test3(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[B:%.*]]) personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br i1 [[B]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    invoke void @use_pointer(ptr [[P]])
+; CHECK-NEXT:            to label %[[IF_END:.*]] unwind label %[[LPAD:.*]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    invoke void @use_pointer(ptr [[P]])
+; CHECK-NEXT:            to label %[[IF_END]] unwind label %[[LPAD]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[R:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    ret void
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -121,15 +160,15 @@ entry:
 
 if.then:
   invoke void @use_pointer(ptr %p)
-          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+  to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
 
 if.else:
   invoke void @use_pointer(ptr %p)
-          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+  to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
 
 lpad:
   %r = landingpad { ptr, i32 }
-       cleanup
+  cleanup
   ret void
 
 if.end:
@@ -139,17 +178,28 @@ if.end:
 
 ; Like test3, but with ARC-relevant exception handling.
 
-; CHECK-LABEL: define void @test4(
-; CHECK: lpad:
-; CHECK-NEXT: %r = landingpad { ptr, i32 }
-; CHECK-NEXT: cleanup
-; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]
-; CHECK-NEXT: ret void
-; CHECK: if.end:
-; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]
-; CHECK-NEXT: ret void
-; CHECK-NEXT: }
 define void @test4(ptr %p, i1 %b) personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test4(
+; CHECK-SAME: ptr [[P:%.*]], i1 [[B:%.*]]) personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br i1 [[B]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    invoke void @use_pointer(ptr [[P]])
+; CHECK-NEXT:            to label %[[IF_END:.*]] unwind label %[[LPAD:.*]]
+; CHECK:       [[IF_ELSE]]:
+; CHECK-NEXT:    invoke void @use_pointer(ptr [[P]])
+; CHECK-NEXT:            to label %[[IF_END]] unwind label %[[LPAD]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[R:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[P]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %0 = call ptr @llvm.objc.retain(ptr %p)
   call void @callee()
@@ -157,15 +207,15 @@ entry:
 
 if.then:
   invoke void @use_pointer(ptr %p)
-          to label %if.end unwind label %lpad
+  to label %if.end unwind label %lpad
 
 if.else:
   invoke void @use_pointer(ptr %p)
-          to label %if.end unwind label %lpad
+  to label %if.end unwind label %lpad
 
 lpad:
   %r = landingpad { ptr, i32 }
-       cleanup
+  cleanup
   call void @llvm.objc.release(ptr %p)
   ret void
 
@@ -177,17 +227,26 @@ if.end:
 ; Don't turn the retainAutoreleaseReturnValue into retain, because it's
 ; for an invoke which we can assume codegen will put immediately prior.
 
-; CHECK-LABEL: define void @test5(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %z)
-; CHECK: }
 define void @test5() personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test5() personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[Z:%.*]] = invoke ptr @returner()
+; CHECK-NEXT:            to label %[[IF_END:.*]] unwind label %[[LPAD:.*]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[R13:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    ret void
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[Z]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %z = invoke ptr @returner()
-          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+  to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
 
 lpad:
   %r13 = landingpad { ptr, i32 }
-          cleanup
+  cleanup
   ret void
 
 if.end:
@@ -197,17 +256,27 @@ if.end:
 
 ; Like test5, but there's intervening code.
 
-; CHECK-LABEL: define void @test6(
-; CHECK: call ptr @llvm.objc.retain(ptr %z)
-; CHECK: }
 define void @test6() personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test6() personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[Z:%.*]] = invoke ptr @returner()
+; CHECK-NEXT:            to label %[[IF_END:.*]] unwind label %[[LPAD:.*]], !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[R13:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            cleanup
+; CHECK-NEXT:    ret void
+; CHECK:       [[IF_END]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[Z]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %z = invoke ptr @returner()
-          to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+  to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
 
 lpad:
   %r13 = landingpad { ptr, i32 }
-          cleanup
+  cleanup
   ret void
 
 if.end:
@@ -219,6 +288,8 @@ if.end:
 declare i32 @__gxx_personality_v0(...)
 declare i32 @__objc_personality_v0(...)
 
-; CHECK: attributes [[NUW]] = { nounwind }
 
 !0 = !{}
+;.
+; CHECK: [[META0]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/nested.ll b/llvm/test/Transforms/ObjCARC/nested.ll
index d03cbd5f54e71..5ad1f450fa8ab 100644
--- a/llvm/test/Transforms/ObjCARC/nested.ll
+++ b/llvm/test/Transforms/ObjCARC/nested.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
 
 %struct.__objcFastEnumerationState = type { i64, ptr, ptr, [5 x i64] }
@@ -25,11 +26,55 @@ declare void @__crasher_block_invoke1(ptr nocapture)
 
 ; Delete a nested retain+release pair.
 
-; CHECK-LABEL: define void @test0(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test0(ptr %a) nounwind {
+; CHECK-LABEL: define void @test0(
+; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL6:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP7:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP7]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR3:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR3]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP5:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL6]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP5]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL6]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0:![0-9]+]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -88,11 +133,56 @@ forcoll.empty:
 
 ; Delete a nested retain+release pair.
 
-; CHECK-LABEL: define void @test2(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test2() nounwind {
+; CHECK-LABEL: define void @test2(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL3:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL3]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL3]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP8]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR4:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR4]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -152,11 +242,56 @@ forcoll.empty:
 
 ; Delete a nested retain+release pair.
 
-; CHECK-LABEL: define void @test4(
-; CHECK: call ptr @llvm.objc.retain
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test4() nounwind {
+; CHECK-LABEL: define void @test4(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[TMP:%.*]] = load ptr, ptr @g, align 8
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP4:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP4]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL8:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP9]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR5:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR5]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP7:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL8]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP7]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL8]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -216,11 +351,56 @@ forcoll.empty:
 
 ; Delete a nested retain+release pair.
 
-; CHECK-LABEL: define void @test5(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test5() nounwind {
+; CHECK-LABEL: define void @test5(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL3:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL3]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL3]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP8]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR4:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR4]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -281,11 +461,57 @@ forcoll.empty:
 ; We handle this now due to the fact that a release just needs a post dominating
 ; use.
 ;
-; CHECK-LABEL: define void @test6(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test6() nounwind {
+; CHECK-LABEL: define void @test6(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL3:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL3]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL3]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP8]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR4:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR4]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP2]])
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -348,11 +574,60 @@ forcoll.empty:
 ; The optimizer currently can't do this, because isn't isn't sophisticated enough in
 ; reasnoning about nesting.
 
-; CHECK-LABEL: define void @test7(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: @llvm.objc.retain
-; CHECK: }
 define void @test7() nounwind {
+; CHECK-LABEL: define void @test7(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL3:%.*]] = call i64 @objc_msgSend(ptr [[TMP1]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL3]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL3]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP8]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP4:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR4:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR4]], align 8
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP2]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP1]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    call void @use(ptr [[TMP3]])
+; CHECK-NEXT:    [[TMP4]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP4]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP1]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP5]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -414,11 +689,61 @@ forcoll.empty:
 
 ; Delete a nested retain+release pair.
 
-; CHECK-LABEL: define void @test8(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK-NOT: @llvm.objc.retain
-; CHECK: }
 define void @test8() nounwind {
+; CHECK-LABEL: define void @test8(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL3:%.*]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP2]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL3]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    [[STATEITEMS_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL3]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP8:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP8]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ], [ [[TMP3:%.*]], %[[FORCOLL_NEXT:.*]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR4:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR4]], align 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP1]], label %[[FORCOLL_NOTMUTATED:.*]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP0]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[STATEITEMS:%.*]] = load ptr, ptr [[STATEITEMS_PTR]], align 8
+; CHECK-NEXT:    [[CURRENTITEM_PTR:%.*]] = getelementptr ptr, ptr [[STATEITEMS]], i64 [[FORCOLL_INDEX]]
+; CHECK-NEXT:    [[TMP2:%.*]] = load ptr, ptr [[CURRENTITEM_PTR]], align 8
+; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq ptr [[TMP2]], null
+; CHECK-NEXT:    br i1 [[TOBOOL]], label %[[FORCOLL_NEXT]], label %[[IF_THEN:.*]]
+; CHECK:       [[IF_THEN]]:
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    br label %[[FORCOLL_NEXT]]
+; CHECK:       [[FORCOLL_NEXT]]:
+; CHECK-NEXT:    [[TMP3]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[TMP3]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP0]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -487,12 +812,58 @@ forcoll.empty:
 ; The optimizer currently can't do this, because of a split loop backedge.
 ; See test9b for the same testcase without a split backedge.
 
-; CHECK-LABEL: define void @test9(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: }
 define void @test9() nounwind {
+; CHECK-LABEL: define void @test9(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL4:%.*]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP3]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL4]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL4]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP9]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ [[PHITMP:%.*]], %[[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE:.*]] ], [ 1, %[[FORCOLL_LOOPBODY_OUTER]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR5:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR5]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP3]], label %[[FORCOLL_NOTMUTATED:.*]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP2]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[FORCOLL_INDEX]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE]]
+; CHECK:       [[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE]]:
+; CHECK-NEXT:    [[PHITMP]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP2]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -553,12 +924,56 @@ forcoll.empty:
 
 ; Like test9, but without a split backedge. TODO: optimize this.
 
-; CHECK-LABEL: define void @test9b(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: @llvm.objc.retain
-; CHECK: }
 define void @test9b() nounwind {
+; CHECK-LABEL: define void @test9b(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL4:%.*]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP3]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL4]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL4]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP9]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ [[PHITMP:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ], [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR5:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR5]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP3]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP2]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[PHITMP]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[PHITMP]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP2]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -618,12 +1033,59 @@ forcoll.empty:
 ; The optimizer currently can't do this, because of a split loop backedge.
 ; See test10b for the same testcase without a split backedge.
 
-; CHECK-LABEL: define void @test10(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retain
-; CHECK: }
 define void @test10() nounwind {
+; CHECK-LABEL: define void @test10(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL4:%.*]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP3]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL4]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL4]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP9]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ [[PHITMP:%.*]], %[[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE:.*]] ], [ 1, %[[FORCOLL_LOOPBODY_OUTER]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR5:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR5]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP3]], label %[[FORCOLL_NOTMUTATED:.*]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP2]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[FORCOLL_INDEX]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE]]
+; CHECK:       [[FORCOLL_NOTMUTATED_FORCOLL_LOOPBODY_CRIT_EDGE]]:
+; CHECK-NEXT:    [[PHITMP]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP2]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -685,12 +1147,57 @@ forcoll.empty:
 
 ; Like test10, but without a split backedge. TODO: optimize this.
 
-; CHECK-LABEL: define void @test10b(
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue
-; CHECK: @llvm.objc.retain
-; CHECK: }
 define void @test10b() nounwind {
+; CHECK-LABEL: define void @test10b(
+; CHECK-SAME: ) #[[ATTR0]] {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[STATE_PTR:%.*]] = alloca [[STRUCT___OBJCFASTENUMERATIONSTATE:%.*]], align 8
+; CHECK-NEXT:    [[ITEMS_PTR:%.*]] = alloca [16 x ptr], align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CALL1:%.*]] = call ptr @returner()
+; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[CALL1]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @callee()
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 8 [[STATE_PTR]], i8 0, i64 64, i1 false)
+; CHECK-NEXT:    [[TMP2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[TMP0]]) #[[ATTR0]]
+; CHECK-NEXT:    [[TMP3:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL4:%.*]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP3]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[ISZERO:%.*]] = icmp eq i64 [[CALL4]], 0
+; CHECK-NEXT:    br i1 [[ISZERO]], label %[[FORCOLL_EMPTY:.*]], label %[[FORCOLL_LOOPINIT:.*]]
+; CHECK:       [[FORCOLL_LOOPINIT]]:
+; CHECK-NEXT:    [[MUTATIONSPTR_PTR:%.*]] = getelementptr inbounds [[STRUCT___OBJCFASTENUMERATIONSTATE]], ptr [[STATE_PTR]], i64 0, i32 2
+; CHECK-NEXT:    [[MUTATIONSPTR:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[FORCOLL_INITIAL_MUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR]], align 8
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY_OUTER:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY_OUTER]]:
+; CHECK-NEXT:    [[FORCOLL_COUNT_PH:%.*]] = phi i64 [ [[CALL4]], %[[FORCOLL_LOOPINIT]] ], [ [[CALL7:%.*]], %[[FORCOLL_REFETCH:.*]] ]
+; CHECK-NEXT:    [[TMP9:%.*]] = icmp ugt i64 [[FORCOLL_COUNT_PH]], 1
+; CHECK-NEXT:    [[UMAX:%.*]] = select i1 [[TMP9]], i64 [[FORCOLL_COUNT_PH]], i64 1
+; CHECK-NEXT:    br label %[[FORCOLL_LOOPBODY:.*]]
+; CHECK:       [[FORCOLL_LOOPBODY]]:
+; CHECK-NEXT:    [[FORCOLL_INDEX:%.*]] = phi i64 [ [[PHITMP:%.*]], %[[FORCOLL_NOTMUTATED:.*]] ], [ 0, %[[FORCOLL_LOOPBODY_OUTER]] ]
+; CHECK-NEXT:    [[MUTATIONSPTR5:%.*]] = load ptr, ptr [[MUTATIONSPTR_PTR]], align 8
+; CHECK-NEXT:    [[STATEMUTATIONS:%.*]] = load i64, ptr [[MUTATIONSPTR5]], align 8
+; CHECK-NEXT:    [[TMP3:%.*]] = icmp eq i64 [[STATEMUTATIONS]], [[FORCOLL_INITIAL_MUTATIONS]]
+; CHECK-NEXT:    br i1 [[TMP3]], label %[[FORCOLL_NOTMUTATED]], label %[[FORCOLL_MUTATED:.*]]
+; CHECK:       [[FORCOLL_MUTATED]]:
+; CHECK-NEXT:    call void @llvm.objc.enumerationMutation(ptr [[TMP2]])
+; CHECK-NEXT:    br label %[[FORCOLL_NOTMUTATED]]
+; CHECK:       [[FORCOLL_NOTMUTATED]]:
+; CHECK-NEXT:    [[PHITMP]] = add i64 [[FORCOLL_INDEX]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[PHITMP]], [[UMAX]]
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FORCOLL_REFETCH]], label %[[FORCOLL_LOOPBODY]]
+; CHECK:       [[FORCOLL_REFETCH]]:
+; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr @"\01L_OBJC_SELECTOR_REFERENCES_", align 8
+; CHECK-NEXT:    [[CALL7]] = call i64 @objc_msgSend(ptr [[TMP2]], ptr [[TMP6]], ptr [[STATE_PTR]], ptr [[ITEMS_PTR]], i64 16)
+; CHECK-NEXT:    [[TMP4:%.*]] = icmp eq i64 [[CALL7]], 0
+; CHECK-NEXT:    br i1 [[TMP4]], label %[[FORCOLL_EMPTY]], label %[[FORCOLL_LOOPBODY_OUTER]]
+; CHECK:       [[FORCOLL_EMPTY]]:
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP2]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP1]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[TMP0]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %state.ptr = alloca %struct.__objcFastEnumerationState, align 8
   %items.ptr = alloca [16 x ptr], align 8
@@ -756,12 +1263,51 @@ forcoll.empty:
 @__block_d_tmp = external hidden constant { i64, i64, ptr, ptr, ptr, ptr }
 @__block_d_tmp5 = external hidden constant { i64, i64, ptr, ptr, ptr, ptr }
 
-; CHECK-LABEL: define void @test11(
-; CHECK: tail call ptr @llvm.objc.retain(ptr %call) [[NUW:#[0-9]+]]
-; CHECK: tail call ptr @llvm.objc.retain(ptr %call) [[NUW]]
-; CHECK: call void @llvm.objc.release(ptr %call) [[NUW]], !clang.imprecise_release !0
-; CHECK: }
 define void @test11() {
+; CHECK-LABEL: define void @test11() {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    [[BLOCK:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
+; CHECK-NEXT:    [[BLOCK9:%.*]] = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
+; CHECK-NEXT:    [[CALL:%.*]] = call ptr @def(), !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK-NEXT:    [[FOO:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 5
+; CHECK-NEXT:    [[BLOCK_ISA:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 0
+; CHECK-NEXT:    store ptr @_NSConcreteStackBlock, ptr [[BLOCK_ISA]], align 8
+; CHECK-NEXT:    [[BLOCK_FLAGS:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 1
+; CHECK-NEXT:    store i32 1107296256, ptr [[BLOCK_FLAGS]], align 8
+; CHECK-NEXT:    [[BLOCK_RESERVED:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 2
+; CHECK-NEXT:    store i32 0, ptr [[BLOCK_RESERVED]], align 4
+; CHECK-NEXT:    [[BLOCK_INVOKE:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 3
+; CHECK-NEXT:    store ptr @__crasher_block_invoke, ptr [[BLOCK_INVOKE]], align 8
+; CHECK-NEXT:    [[BLOCK_D:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK]], i64 0, i32 4
+; CHECK-NEXT:    store ptr @__block_d_tmp, ptr [[BLOCK_D]], align 8
+; CHECK-NEXT:    [[FOO2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    store ptr [[FOO2]], ptr [[FOO]], align 8
+; CHECK-NEXT:    [[FOO5:%.*]] = call ptr @llvm.objc.retainBlock(ptr [[BLOCK]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use(ptr [[FOO5]]), !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[FOO5]]) #[[ATTR0]]
+; CHECK-NEXT:    [[STRONGDESTROY:%.*]] = load ptr, ptr [[FOO]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[STRONGDESTROY]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[FOO10:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 5
+; CHECK-NEXT:    [[BLOCK_ISA11:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 0
+; CHECK-NEXT:    store ptr @_NSConcreteStackBlock, ptr [[BLOCK_ISA11]], align 8
+; CHECK-NEXT:    [[BLOCK_FLAGS12:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 1
+; CHECK-NEXT:    store i32 1107296256, ptr [[BLOCK_FLAGS12]], align 8
+; CHECK-NEXT:    [[BLOCK_RESERVED13:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 2
+; CHECK-NEXT:    store i32 0, ptr [[BLOCK_RESERVED13]], align 4
+; CHECK-NEXT:    [[BLOCK_INVOKE14:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 3
+; CHECK-NEXT:    store ptr @__crasher_block_invoke1, ptr [[BLOCK_INVOKE14]], align 8
+; CHECK-NEXT:    [[BLOCK_D15:%.*]] = getelementptr inbounds <{ ptr, i32, i32, ptr, ptr, ptr }>, ptr [[BLOCK9]], i64 0, i32 4
+; CHECK-NEXT:    store ptr @__block_d_tmp5, ptr [[BLOCK_D15]], align 8
+; CHECK-NEXT:    store ptr [[CALL]], ptr [[FOO10]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[FOO21:%.*]] = call ptr @llvm.objc.retainBlock(ptr [[BLOCK9]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use(ptr [[FOO21]]), !clang.arc.no_objc_arc_exceptions [[META0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[FOO21]]) #[[ATTR0]]
+; CHECK-NEXT:    [[STRONGDESTROY25:%.*]] = load ptr, ptr [[FOO10]], align 8
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[STRONGDESTROY25]]) #[[ATTR0]], !clang.imprecise_release [[META0]]
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    ret void
+;
 entry:
   %block = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
   %block9 = alloca <{ ptr, i32, i32, ptr, ptr, ptr }>, align 8
@@ -807,6 +1353,6 @@ entry:
 }
 
 
-; CHECK: attributes [[NUW]] = { nounwind }
-; CHECK: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: write) }
-; CHECK: attributes #2 = { nonlazybind }
+;.
+; CHECK: [[META0]] = !{}
+;.
diff --git a/llvm/test/Transforms/ObjCARC/split-backedge.ll b/llvm/test/Transforms/ObjCARC/split-backedge.ll
index ed855541cfb54..c28071f5908f5 100644
--- a/llvm/test/Transforms/ObjCARC/split-backedge.ll
+++ b/llvm/test/Transforms/ObjCARC/split-backedge.ll
@@ -1,28 +1,46 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
 ; RUN: opt -S -passes=objc-arc < %s | FileCheck %s
 
 ; Handle a retain+release pair entirely contained within a split loop backedge.
 ; rdar://11256239
 
-; CHECK-LABEL: define void @test0(
-; CHECK: call ptr @llvm.objc.retain(ptr %call) [[NUW:#[0-9]+]]
-; CHECK: call ptr @llvm.objc.retain(ptr %call) [[NUW]]
-; CHECK: call ptr @llvm.objc.retain(ptr %cond) [[NUW]]
-; CHECK: call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK: call void @llvm.objc.release(ptr %call) [[NUW]]
-; CHECK: call void @llvm.objc.release(ptr %cond) [[NUW]]
 define void @test0() personality ptr @__objc_personality_v0 {
+; CHECK-LABEL: define void @test0() personality ptr @__objc_personality_v0 {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    br label %[[WHILE_BODY:.*]]
+; CHECK:       [[WHILE_BODY]]:
+; CHECK-NEXT:    [[CALL:%.*]] = invoke ptr @returner()
+; CHECK-NEXT:            to label %[[INVOKE_CONT:.*]] unwind label %[[LPAD:.*]], !clang.arc.no_objc_arc_exceptions [[META0:![0-9]+]]
+; CHECK:       [[INVOKE_CONT]]:
+; CHECK-NEXT:    [[T0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    [[T1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    [[CALL_I1:%.*]] = invoke ptr @returner()
+; CHECK-NEXT:            to label %[[INVOKE_CONT1:.*]] unwind label %[[LPAD]]
+; CHECK:       [[INVOKE_CONT1]]:
+; CHECK-NEXT:    [[COND:%.*]] = select i1 undef, ptr null, ptr [[CALL]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @llvm.objc.release(ptr [[CALL]]) #[[ATTR0]]
+; CHECK-NEXT:    call void @use_pointer(ptr [[COND]])
+; CHECK-NEXT:    [[TMP0:%.*]] = tail call ptr @llvm.objc.retain(ptr [[COND]]) #[[ATTR0]]
+; CHECK-NEXT:    br label %[[WHILE_BODY]]
+; CHECK:       [[LPAD]]:
+; CHECK-NEXT:    [[T4:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT:            catch ptr null
+; CHECK-NEXT:    ret void
+;
 entry:
   br label %while.body
 
 while.body:                                       ; preds = %while.cond
   %call = invoke ptr @returner()
-          to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
+  to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
 
 invoke.cont:                                      ; preds = %while.body
   %t0 = call ptr @llvm.objc.retain(ptr %call) nounwind
   %t1 = call ptr @llvm.objc.retain(ptr %call) nounwind
   %call.i1 = invoke ptr @returner()
-          to label %invoke.cont1 unwind label %lpad
+  to label %invoke.cont1 unwind label %lpad
 
 invoke.cont1:                                     ; preds = %invoke.cont
   %cond = select i1 undef, ptr null, ptr %call
@@ -35,7 +53,7 @@ invoke.cont1:                                     ; preds = %invoke.cont
 
 lpad:                                             ; preds = %invoke.cont, %while.body
   %t4 = landingpad { ptr, i32 }
-          catch ptr null
+  catch ptr null
   ret void
 }
 
@@ -47,4 +65,6 @@ declare void @use_pointer(ptr)
 
 !0 = !{}
 
-; CHECK: attributes [[NUW]] = { nounwind }
+;.
+; CHECK: [[META0]] = !{}
+;.



More information about the llvm-commits mailing list