<div dir="ltr"><div>Please if at all possible make smaller/incremental patches.<br><br>In any case, somewhere in all this, Analysis/ObjCARCUtils.h was introduced and included from llvm/IR, violating library layering. (Analysis depends on IR, not the other way around)<br><br>So I moved this header into IR (please fix otherwise if there's a better answer - but the utilities looked generally applicable to IR) and also fixed a couple of implementation bugs ("LIB" in the header guard macro - we don't usually do that, and the use of non-member "static" in the header - that can lead to ODR violations). In git commit a2a55def354df2cd4de0b1cbd6b2795a07e6905a<br><br></div><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Mar 4, 2021 at 11:23 AM Akira Hatanaka via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Akira Hatanaka<br>
Date: 2021-03-04T11:22:30-08:00<br>
New Revision: 1900503595cbb84a4c6e140a9ba1a2c574c0586d<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/1900503595cbb84a4c6e140a9ba1a2c574c0586d" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/1900503595cbb84a4c6e140a9ba1a2c574c0586d</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/1900503595cbb84a4c6e140a9ba1a2c574c0586d.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/1900503595cbb84a4c6e140a9ba1a2c574c0586d.diff</a><br>
<br>
LOG: [ObjC][ARC] Use operand bundle 'clang.arc.attachedcall' instead of<br>
explicitly emitting retainRV or claimRV calls in the IR<br>
<br>
This reapplies ed4718eccb12bd42214ca4fb17d196d49561c0c7, which was reverted<br>
because it was causing a miscompile. The bug that was causing the miscompile<br>
has been fixed in 75805dce5ff874676f3559c069fcd6737838f5c0.<br>
<br>
Original commit message:<br>
<br>
Background:<br>
<br>
This fixes a longstanding problem where llvm breaks ARC's autorelease<br>
optimization (see the link below) by separating calls from the marker<br>
instructions or retainRV/claimRV calls. The backend changes are in<br>
<a href="https://reviews.llvm.org/D92569" rel="noreferrer" target="_blank">https://reviews.llvm.org/D92569</a>.<br>
<br>
<a href="https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-autoreleasereturnvalue" rel="noreferrer" target="_blank">https://clang.llvm.org/docs/AutomaticReferenceCounting.html#arc-runtime-objc-autoreleasereturnvalue</a><br>
<br>
What this patch does to fix the problem:<br>
<br>
- The front-end adds operand bundle "clang.arc.attachedcall" to calls,<br>
  which indicates the call is implicitly followed by a marker<br>
  instruction and an implicit retainRV/claimRV call that consumes the<br>
  call result. In addition, it emits a call to<br>
  @llvm.objc.clang.arc.noop.use, which consumes the call result, to<br>
  prevent the middle-end passes from changing the return type of the<br>
  called function. This is currently done only when the target is arm64<br>
  and the optimization level is higher than -O0.<br>
<br>
- ARC optimizer temporarily emits retainRV/claimRV calls after the calls<br>
  with the operand bundle in the IR and removes the inserted calls after<br>
  processing the function.<br>
<br>
- ARC contract pass emits retainRV/claimRV calls after the call with the<br>
  operand bundle. It doesn't remove the operand bundle on the call since<br>
  the backend needs it to emit the marker instruction. The retainRV and<br>
  claimRV calls are emitted late in the pipeline to prevent optimization<br>
  passes from transforming the IR in a way that makes it harder for the<br>
  ARC middle-end passes to figure out the def-use relationship between<br>
  the call and the retainRV/claimRV calls (which is the cause of<br>
  PR31925).<br>
<br>
- The function inliner removes an autoreleaseRV call in the callee if<br>
  nothing in the callee prevents it from being paired up with the<br>
  retainRV/claimRV call in the caller. It then inserts a release call if<br>
  claimRV is attached to the call since autoreleaseRV+claimRV is<br>
  equivalent to a release. If it cannot find an autoreleaseRV call, it<br>
  tries to transfer the operand bundle to a function call in the callee.<br>
  This is important since the ARC optimizer can remove the autoreleaseRV<br>
  returning the callee result, which makes it impossible to pair it up<br>
  with the retainRV/claimRV call in the caller. If that fails, it simply<br>
  emits a retain call in the IR if retainRV is attached to the call and<br>
  does nothing if claimRV is attached to it.<br>
<br>
- SCCP refrains from replacing the return value of a call with a<br>
  constant value if the call has the operand bundle. This ensures the<br>
  call always has at least one user (the call to<br>
  @llvm.objc.clang.arc.noop.use).<br>
<br>
- This patch also fixes a bug in replaceUsesOfNonProtoConstant where<br>
  multiple operand bundles of the same kind were being added to a call.<br>
<br>
Future work:<br>
<br>
- Use the operand bundle on x86-64.<br>
<br>
- Fix the auto upgrader to convert call+retainRV/claimRV pairs into<br>
  calls with the operand bundles.<br>
<br>
rdar://71443534<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D92808" rel="noreferrer" target="_blank">https://reviews.llvm.org/D92808</a><br>
<br>
Added: <br>
    clang/test/CodeGenObjC/arc-rv-attr.m<br>
    llvm/include/llvm/Analysis/ObjCARCUtil.h<br>
    llvm/test/Transforms/Inline/inline-retainRV-call.ll<br>
    llvm/test/Transforms/ObjCARC/contract-rv-attr.ll<br>
    llvm/test/Transforms/SCCP/clang-arc-rv.ll<br>
<br>
Modified: <br>
    clang/lib/CodeGen/CGObjC.cpp<br>
    clang/lib/CodeGen/CodeGenFunction.h<br>
    clang/lib/CodeGen/CodeGenModule.cpp<br>
    clang/lib/CodeGen/CodeGenModule.h<br>
    clang/test/CodeGenObjC/arc-unsafeclaim.m<br>
    llvm/docs/LangRef.rst<br>
    llvm/include/llvm/IR/InstrTypes.h<br>
    llvm/include/llvm/IR/Intrinsics.td<br>
    llvm/include/llvm/IR/LLVMContext.h<br>
    llvm/lib/Analysis/ObjCARCInstKind.cpp<br>
    llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
    llvm/lib/IR/AutoUpgrade.cpp<br>
    llvm/lib/IR/Instructions.cpp<br>
    llvm/lib/IR/LLVMContext.cpp<br>
    llvm/lib/IR/Verifier.cpp<br>
    llvm/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
    llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h<br>
    llvm/lib/Transforms/ObjCARC/ObjCARC.cpp<br>
    llvm/lib/Transforms/ObjCARC/ObjCARC.h<br>
    llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp<br>
    llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp<br>
    llvm/lib/Transforms/ObjCARC/PtrState.cpp<br>
    llvm/lib/Transforms/ObjCARC/PtrState.h<br>
    llvm/lib/Transforms/Scalar/SCCP.cpp<br>
    llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp<br>
    llvm/lib/Transforms/Utils/InlineFunction.cpp<br>
    llvm/test/Bitcode/operand-bundles-bc-analyzer.ll<br>
    llvm/test/CodeGen/AArch64/call-rv-marker.ll<br>
    llvm/test/Transforms/DeadArgElim/deadretval.ll<br>
    llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll<br>
    llvm/test/Transforms/ObjCARC/contract.ll<br>
    llvm/test/Transforms/ObjCARC/intrinsic-use.ll<br>
    llvm/test/Transforms/ObjCARC/rv.ll<br>
    llvm/test/Transforms/TailCallElim/deopt-bundle.ll<br>
    llvm/test/Verifier/operand-bundles.ll<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp<br>
index 3f930c76fe0a2..663666b6bf8b8 100644<br>
--- a/clang/lib/CodeGen/CGObjC.cpp<br>
+++ b/clang/lib/CodeGen/CGObjC.cpp<br>
@@ -23,6 +23,7 @@<br>
 #include "clang/Basic/Diagnostic.h"<br>
 #include "clang/CodeGen/CGFunctionInfo.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/BinaryFormat/MachO.h"<br>
 #include "llvm/IR/DataLayout.h"<br>
 #include "llvm/IR/InlineAsm.h"<br>
@@ -2078,6 +2079,15 @@ void CodeGenFunction::EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values) {<br>
   EmitNounwindRuntimeCall(fn, values);<br>
 }<br>
<br>
+/// Emit a call to "clang.arc.noop.use", which consumes the result of a call<br>
+/// that has operand bundle "clang.arc.attachedcall".<br>
+void CodeGenFunction::EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values) {<br>
+  llvm::Function *&fn = CGM.getObjCEntrypoints().clang_arc_noop_use;<br>
+  if (!fn)<br>
+    fn = CGM.getIntrinsic(llvm::Intrinsic::objc_clang_arc_noop_use);<br>
+  EmitNounwindRuntimeCall(fn, values);<br>
+}<br>
+<br>
 static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM, llvm::Value *RTF) {<br>
   if (auto *F = dyn_cast<llvm::Function>(RTF)) {<br>
     // If the target runtime doesn't naturally support ARC, emit weak<br>
@@ -2304,10 +2314,11 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {<br>
     // with this marker yet, so leave a breadcrumb for the ARC<br>
     // optimizer to pick up.<br>
     } else {<br>
-      const char *markerKey = "clang.arc.retainAutoreleasedReturnValueMarker";<br>
-      if (!CGF.CGM.getModule().getModuleFlag(markerKey)) {<br>
+      const char *retainRVMarkerKey = llvm::objcarc::getRVMarkerModuleFlagStr();<br>
+      if (!CGF.CGM.getModule().getModuleFlag(retainRVMarkerKey)) {<br>
         auto *str = llvm::MDString::get(CGF.getLLVMContext(), assembly);<br>
-        CGF.CGM.getModule().addModuleFlag(llvm::Module::Error, markerKey, str);<br>
+        CGF.CGM.getModule().addModuleFlag(llvm::Module::Error,<br>
+                                          retainRVMarkerKey, str);<br>
       }<br>
     }<br>
   }<br>
@@ -2317,6 +2328,47 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {<br>
     CGF.Builder.CreateCall(marker, None, CGF.getBundlesForFunclet(marker));<br>
 }<br>
<br>
+static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,<br>
+                                               bool IsRetainRV,<br>
+                                               CodeGenFunction &CGF) {<br>
+  emitAutoreleasedReturnValueMarker(CGF);<br>
+<br>
+  // Add operand bundle "clang.arc.attachedcall" to the call instead of emitting<br>
+  // retainRV or claimRV calls in the IR. We currently do this only when the<br>
+  // optimization level isn't -O0 since global-isel, which is currently run at<br>
+  // -O0, doesn't know about the operand bundle.<br>
+<br>
+  // FIXME: Do this when the target isn't aarch64.<br>
+  if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&<br>
+      CGF.CGM.getTarget().getTriple().isAArch64()) {<br>
+    llvm::Value *bundleArgs[] = {llvm::ConstantInt::get(<br>
+        CGF.Int64Ty,<br>
+        llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};<br>
+    llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);<br>
+    auto *oldCall = cast<llvm::CallBase>(value);<br>
+    llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(<br>
+        oldCall, llvm::LLVMContext::OB_clang_arc_attachedcall, OB, oldCall);<br>
+    newCall->copyMetadata(*oldCall);<br>
+    oldCall->replaceAllUsesWith(newCall);<br>
+    oldCall->eraseFromParent();<br>
+    CGF.EmitARCNoopIntrinsicUse(newCall);<br>
+    return newCall;<br>
+  }<br>
+<br>
+  bool isNoTail =<br>
+      CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail();<br>
+  llvm::CallInst::TailCallKind tailKind =<br>
+      isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None;<br>
+  ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();<br>
+  llvm::Function *&EP = IsRetainRV<br>
+                            ? EPs.objc_retainAutoreleasedReturnValue<br>
+                            : EPs.objc_unsafeClaimAutoreleasedReturnValue;<br>
+  llvm::Intrinsic::ID IID =<br>
+      IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue<br>
+                 : llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;<br>
+  return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind);<br>
+}<br>
+<br>
 /// Retain the given object which is the result of a function call.<br>
 ///   call i8* \@objc_retainAutoreleasedReturnValue(i8* %value)<br>
 ///<br>
@@ -2324,15 +2376,7 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {<br>
 /// call with completely <br>
diff erent semantics.<br>
 llvm::Value *<br>
 CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {<br>
-  emitAutoreleasedReturnValueMarker(*this);<br>
-  llvm::CallInst::TailCallKind tailKind =<br>
-      CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail()<br>
-          ? llvm::CallInst::TCK_NoTail<br>
-          : llvm::CallInst::TCK_None;<br>
-  return emitARCValueOperation(<br>
-      *this, value, nullptr,<br>
-      CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,<br>
-      llvm::Intrinsic::objc_retainAutoreleasedReturnValue, tailKind);<br>
+  return emitOptimizedARCReturnCall(value, true, *this);<br>
 }<br>
<br>
 /// Claim a possibly-autoreleased return value at +0.  This is only<br>
@@ -2344,15 +2388,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {<br>
 ///   call i8* \@objc_unsafeClaimAutoreleasedReturnValue(i8* %value)<br>
 llvm::Value *<br>
 CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) {<br>
-  emitAutoreleasedReturnValueMarker(*this);<br>
-  llvm::CallInst::TailCallKind tailKind =<br>
-      CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail()<br>
-          ? llvm::CallInst::TCK_NoTail<br>
-          : llvm::CallInst::TCK_None;<br>
-  return emitARCValueOperation(<br>
-      *this, value, nullptr,<br>
-      CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue,<br>
-      llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue, tailKind);<br>
+  return emitOptimizedARCReturnCall(value, false, *this);<br>
 }<br>
<br>
 /// Release the given object.<br>
<br>
diff  --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h<br>
index 279ee857ecd22..8ef0de018a98b 100644<br>
--- a/clang/lib/CodeGen/CodeGenFunction.h<br>
+++ b/clang/lib/CodeGen/CodeGenFunction.h<br>
@@ -4216,6 +4216,8 @@ class CodeGenFunction : public CodeGenTypeCache {<br>
<br>
   void EmitARCIntrinsicUse(ArrayRef<llvm::Value*> values);<br>
<br>
+  void EmitARCNoopIntrinsicUse(ArrayRef<llvm::Value *> values);<br>
+<br>
   static Destroyer destroyARCStrongImprecise;<br>
   static Destroyer destroyARCStrongPrecise;<br>
   static Destroyer destroyARCWeak;<br>
<br>
diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp<br>
index b23d995683bf7..5623bd7542ec5 100644<br>
--- a/clang/lib/CodeGen/CodeGenModule.cpp<br>
+++ b/clang/lib/CodeGen/CodeGenModule.cpp<br>
@@ -4573,7 +4573,6 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,<br>
<br>
   llvm::Type *newRetTy = newFn->getReturnType();<br>
   SmallVector<llvm::Value*, 4> newArgs;<br>
-  SmallVector<llvm::OperandBundleDef, 1> newBundles;<br>
<br>
   for (llvm::Value::use_iterator ui = old->use_begin(), ue = old->use_end();<br>
          ui != ue; ) {<br>
@@ -4630,6 +4629,7 @@ static void replaceUsesOfNonProtoConstant(llvm::Constant *old,<br>
     newArgs.append(callSite->arg_begin(), callSite->arg_begin() + argNo);<br>
<br>
     // Copy over any operand bundles.<br>
+    SmallVector<llvm::OperandBundleDef, 1> newBundles;<br>
     callSite->getOperandBundlesAsDefs(newBundles);<br>
<br>
     llvm::CallBase *newCall;<br>
<br>
diff  --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h<br>
index 409ebd3df07fe..d495a169b609b 100644<br>
--- a/clang/lib/CodeGen/CodeGenModule.h<br>
+++ b/clang/lib/CodeGen/CodeGenModule.h<br>
@@ -210,6 +210,9 @@ struct ObjCEntrypoints {<br>
<br>
   /// void clang.arc.use(...);<br>
   llvm::Function *clang_arc_use;<br>
+<br>
+  /// void clang.arc.noop.use(...);<br>
+  llvm::Function *clang_arc_noop_use;<br>
 };<br>
<br>
 /// This class records statistics on instrumentation based profiling.<br>
<br>
diff  --git a/clang/test/CodeGenObjC/arc-rv-attr.m b/clang/test/CodeGenObjC/arc-rv-attr.m<br>
new file mode 100644<br>
index 0000000000000..3b769de1443c7<br>
--- /dev/null<br>
+++ b/clang/test/CodeGenObjC/arc-rv-attr.m<br>
@@ -0,0 +1,177 @@<br>
+// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK<br>
+<br>
+@class A;<br>
+<br>
+A *makeA(void);<br>
+<br>
+void test_assign() {<br>
+  __unsafe_unretained id x;<br>
+  x = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_assign()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_assign_assign() {<br>
+  __unsafe_unretained id x, y;<br>
+  x = y = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_assign_assign()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_strong_assign_assign() {<br>
+  __strong id x;<br>
+  __unsafe_unretained id y;<br>
+  x = y = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    [[OLD:%.*]] = load i8*, i8** [[X]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[OLD]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    [[T0:%.*]] = load i8*, i8** [[X]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[T0]])<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_assign_strong_assign() {<br>
+  __unsafe_unretained id x;<br>
+  __strong id y;<br>
+  x = y = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    [[OLD:%.*]] = load i8*, i8** [[Y]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[OLD]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    [[T0:%.*]] = load i8*, i8** [[Y]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[T0]])<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_init() {<br>
+  __unsafe_unretained id x = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_init()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_init_assignment() {<br>
+  __unsafe_unretained id x;<br>
+  __unsafe_unretained id y = x = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_init_assignment()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_strong_init_assignment() {<br>
+  __unsafe_unretained id x;<br>
+  __strong id y = x = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    [[T0:%.*]] = load i8*, i8** [[Y]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[T0]])<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_init_strong_assignment() {<br>
+  __strong id x;<br>
+  __unsafe_unretained id y = x = makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()<br>
+// CHECK:         [[X:%.*]] = alloca i8*<br>
+// CHECK:         [[Y:%.*]] = alloca i8*<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*<br>
+// CHECK-NEXT:    [[OLD:%.*]] = load i8*, i8** [[X]]<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[X]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[OLD]])<br>
+// CHECK-NEXT:    store i8* [[T1]], i8** [[Y]]<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    [[T0:%.*]] = load i8*, i8** [[X]]<br>
+// CHECK-NEXT:    call void @llvm.objc.release(i8* [[T0]])<br>
+// CHECK-NEXT:    bitcast<br>
+// CHECK-NEXT:    lifetime.end<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_ignored() {<br>
+  makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_ignored()<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+void test_cast_to_void() {<br>
+  (void) makeA();<br>
+}<br>
+// CHECK-LABEL: define{{.*}} void @test_cast_to_void()<br>
+// CHECK:         [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]<br>
+// CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])<br>
+// CHECK-NEXT:    ret void<br>
+<br>
+// This is always at the end of the module.<br>
+<br>
+// CHECK-OPTIMIZED: !llvm.module.flags = !{!0,<br>
+// CHECK-OPTIMIZED: !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov{{.*}}marker for objc_retainAutoreleaseReturnValue"}<br>
<br>
diff  --git a/clang/test/CodeGenObjC/arc-unsafeclaim.m b/clang/test/CodeGenObjC/arc-unsafeclaim.m<br>
index 8f95d1edc96c5..08ff8eca8da51 100644<br>
--- a/clang/test/CodeGenObjC/arc-unsafeclaim.m<br>
+++ b/clang/test/CodeGenObjC/arc-unsafeclaim.m<br>
@@ -4,11 +4,10 @@<br>
 //   Make sure it works on x86-32.<br>
 // RUN: %clang_cc1 -triple i386-apple-darwin11 -fobjc-runtime=macosx-fragile-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL<br>
<br>
-//   Make sure it works on ARM.<br>
+//   Make sure it works on ARM64.<br>
 // RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL<br>
-// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL<br>
<br>
-//   Make sure it works on ARM64.<br>
+//   Make sure it works on ARM.<br>
 // RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=CHECK-MARKED -check-prefix=CALL<br>
 // RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL<br>
<br>
<br>
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst<br>
index fef7a2af8d15f..343aeaec78bb8 100644<br>
--- a/llvm/docs/LangRef.rst<br>
+++ b/llvm/docs/LangRef.rst<br>
@@ -2328,6 +2328,19 @@ When lowered, any relocated value will be recorded in the corresponding<br>
 :ref:`stackmap entry <statepoint-stackmap-format>`.  See the intrinsic description<br>
 for further details.<br>
<br>
+ObjC ARC Attached Call Operand Bundles<br>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
+<br>
+A ``"clang.arc.attachedcall`` operand bundle on a call indicates the call is<br>
+implicitly followed by a marker instruction and a call to an ObjC runtime<br>
+function that uses the result of the call. If the argument passed to the operand<br>
+bundle is 0, ``@objc_retainAutoreleasedReturnValue`` is called. If 1 is passed,<br>
+``@objc_unsafeClaimAutoreleasedReturnValue`` is called. A call with this bundle<br>
+implicitly uses its return value.<br>
+<br>
+The operand bundle is needed to ensure the call is immediately followed by the<br>
+marker instruction or the ObjC runtime call in the final output.<br>
+<br>
 .. _moduleasm:<br>
<br>
 Module-Level Inline Assembly<br>
<br>
diff  --git a/llvm/include/llvm/Analysis/ObjCARCUtil.h b/llvm/include/llvm/Analysis/ObjCARCUtil.h<br>
new file mode 100644<br>
index 0000000000000..9345c892ff399<br>
--- /dev/null<br>
+++ b/llvm/include/llvm/Analysis/ObjCARCUtil.h<br>
@@ -0,0 +1,50 @@<br>
+//===- ObjCARCUtil.h - ObjC ARC Utility Functions ---------------*- C++ -*-===//<br>
+//<br>
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.<br>
+// See <a href="https://llvm.org/LICENSE.txt" rel="noreferrer" target="_blank">https://llvm.org/LICENSE.txt</a> for license information.<br>
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+/// This file defines ARC utility functions which are used by various parts of<br>
+/// the compiler.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_LIB_ANALYSIS_OBJCARCUTIL_H<br>
+#define LLVM_LIB_ANALYSIS_OBJCARCUTIL_H<br>
+<br>
+#include "llvm/IR/InstrTypes.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+<br>
+namespace llvm {<br>
+namespace objcarc {<br>
+<br>
+static inline const char *getRVMarkerModuleFlagStr() {<br>
+  return "clang.arc.retainAutoreleasedReturnValueMarker";<br>
+}<br>
+<br>
+enum AttachedCallOperandBundle : unsigned { RVOB_Retain, RVOB_Claim };<br>
+<br>
+static AttachedCallOperandBundle<br>
+getAttachedCallOperandBundleEnum(bool IsRetain) {<br>
+  return IsRetain ? RVOB_Retain : RVOB_Claim;<br>
+}<br>
+<br>
+static inline bool hasAttachedCallOpBundle(const CallBase *CB, bool IsRetain) {<br>
+  auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall);<br>
+  if (!B.hasValue())<br>
+    return false;<br>
+  return cast<ConstantInt>(B->Inputs[0])->getZExtValue() ==<br>
+         getAttachedCallOperandBundleEnum(IsRetain);<br>
+}<br>
+<br>
+static inline bool hasAttachedCallOpBundle(const CallBase *CB) {<br>
+  return CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall)<br>
+      .hasValue();<br>
+}<br>
+<br>
+} // end namespace objcarc<br>
+} // end namespace llvm<br>
+<br>
+#endif<br>
<br>
diff  --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h<br>
index 906264b7d91d9..5c1d2bdd296ea 100644<br>
--- a/llvm/include/llvm/IR/InstrTypes.h<br>
+++ b/llvm/include/llvm/IR/InstrTypes.h<br>
@@ -1223,6 +1223,15 @@ class CallBase : public Instruction {<br>
                           OperandBundleDef Bundle,<br>
                           Instruction *InsertPt = nullptr);<br>
<br>
+  /// Create a clone of \p CB with operand bundle \p OB added.<br>
+  static CallBase *addOperandBundle(CallBase *CB, uint32_t ID,<br>
+                                    OperandBundleDef OB,<br>
+                                    Instruction *InsertPt = nullptr);<br>
+<br>
+  /// Create a clone of \p CB with operand bundle \p ID removed.<br>
+  static CallBase *removeOperandBundle(CallBase *CB, uint32_t ID,<br>
+                                       Instruction *InsertPt = nullptr);<br>
+<br>
   static bool classof(const Instruction *I) {<br>
     return I->getOpcode() == Instruction::Call ||<br>
            I->getOpcode() == Instruction::Invoke ||<br>
<br>
diff  --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td<br>
index 385fdfa34b1b9..2ada767fa0a26 100644<br>
--- a/llvm/include/llvm/IR/Intrinsics.td<br>
+++ b/llvm/include/llvm/IR/Intrinsics.td<br>
@@ -450,6 +450,9 @@ def int_objc_storeWeak                      : Intrinsic<[llvm_ptr_ty],<br>
                                                          llvm_ptr_ty]>;<br>
 def int_objc_clang_arc_use                  : Intrinsic<[],<br>
                                                         [llvm_vararg_ty]>;<br>
+def int_objc_clang_arc_noop_use : DefaultAttrsIntrinsic<[],<br>
+                                                        [llvm_vararg_ty],<br>
+                                                        [IntrInaccessibleMemOnly]>;<br>
 def int_objc_unsafeClaimAutoreleasedReturnValue : Intrinsic<[llvm_ptr_ty],<br>
                                                             [llvm_ptr_ty]>;<br>
 def int_objc_retainedObject                 : Intrinsic<[llvm_ptr_ty],<br>
<br>
diff  --git a/llvm/include/llvm/IR/LLVMContext.h b/llvm/include/llvm/IR/LLVMContext.h<br>
index 16eb5c69d3b78..3bd889485dd1d 100644<br>
--- a/llvm/include/llvm/IR/LLVMContext.h<br>
+++ b/llvm/include/llvm/IR/LLVMContext.h<br>
@@ -87,12 +87,13 @@ class LLVMContext {<br>
   /// operand bundle tags without comparing strings. Keep this in sync with<br>
   /// LLVMContext::LLVMContext().<br>
   enum : unsigned {<br>
-    OB_deopt = 0,         // "deopt"<br>
-    OB_funclet = 1,       // "funclet"<br>
-    OB_gc_transition = 2, // "gc-transition"<br>
-    OB_cfguardtarget = 3, // "cfguardtarget"<br>
-    OB_preallocated = 4,  // "preallocated"<br>
-    OB_gc_live = 5,       // "gc-live"<br>
+    OB_deopt = 0,                  // "deopt"<br>
+    OB_funclet = 1,                // "funclet"<br>
+    OB_gc_transition = 2,          // "gc-transition"<br>
+    OB_cfguardtarget = 3,          // "cfguardtarget"<br>
+    OB_preallocated = 4,           // "preallocated"<br>
+    OB_gc_live = 5,                // "gc-live"<br>
+    OB_clang_arc_attachedcall = 6, // "clang.arc.attachedcall"<br>
   };<br>
<br>
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.<br>
<br>
diff  --git a/llvm/lib/Analysis/ObjCARCInstKind.cpp b/llvm/lib/Analysis/ObjCARCInstKind.cpp<br>
index 9519078042271..704d15f3280dc 100644<br>
--- a/llvm/lib/Analysis/ObjCARCInstKind.cpp<br>
+++ b/llvm/lib/Analysis/ObjCARCInstKind.cpp<br>
@@ -140,6 +140,7 @@ ARCInstKind llvm::objcarc::GetFunctionClass(const Function *F) {<br>
     return ARCInstKind::User;<br>
   case Intrinsic::objc_sync_exit:<br>
     return ARCInstKind::User;<br>
+  case Intrinsic::objc_clang_arc_noop_use:<br>
   case Intrinsic::objc_arc_annotation_topdown_bbstart:<br>
   case Intrinsic::objc_arc_annotation_topdown_bbend:<br>
   case Intrinsic::objc_arc_annotation_bottomup_bbstart:<br>
<br>
diff  --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
index 3e574dd8fb72d..39730d03502b7 100644<br>
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp<br>
@@ -2784,11 +2784,11 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {<br>
<br>
   // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't<br>
   // have to do anything here to lower funclet bundles.<br>
-  assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt,<br>
-                                        LLVMContext::OB_gc_transition,<br>
-                                        LLVMContext::OB_gc_live,<br>
-                                        LLVMContext::OB_funclet,<br>
-                                        LLVMContext::OB_cfguardtarget}) &&<br>
+  assert(!I.hasOperandBundlesOtherThan(<br>
+             {LLVMContext::OB_deopt, LLVMContext::OB_gc_transition,<br>
+              LLVMContext::OB_gc_live, LLVMContext::OB_funclet,<br>
+              LLVMContext::OB_cfguardtarget,<br>
+              LLVMContext::OB_clang_arc_attachedcall}) &&<br>
          "Cannot lower invokes with arbitrary operand bundles yet!");<br>
<br>
   const Value *Callee(I.getCalledOperand());<br>
@@ -7895,7 +7895,8 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {<br>
   // CFGuardTarget bundles are lowered in LowerCallTo.<br>
   assert(!I.hasOperandBundlesOtherThan(<br>
              {LLVMContext::OB_deopt, LLVMContext::OB_funclet,<br>
-              LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated}) &&<br>
+              LLVMContext::OB_cfguardtarget, LLVMContext::OB_preallocated,<br>
+              LLVMContext::OB_clang_arc_attachedcall}) &&<br>
          "Cannot lower calls with arbitrary operand bundles!");<br>
<br>
   SDValue Callee = getValue(I.getCalledOperand());<br>
<br>
diff  --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp<br>
index 1250b5d2a906f..8ca091d436c88 100644<br>
--- a/llvm/lib/IR/AutoUpgrade.cpp<br>
+++ b/llvm/lib/IR/AutoUpgrade.cpp<br>
@@ -14,14 +14,15 @@<br>
<br>
 #include "llvm/IR/AutoUpgrade.h"<br>
 #include "llvm/ADT/StringSwitch.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/DIBuilder.h"<br>
 #include "llvm/IR/DebugInfo.h"<br>
 #include "llvm/IR/DiagnosticInfo.h"<br>
 #include "llvm/IR/Function.h"<br>
 #include "llvm/IR/IRBuilder.h"<br>
-#include "llvm/IR/Instruction.h"<br>
 #include "llvm/IR/InstVisitor.h"<br>
+#include "llvm/IR/Instruction.h"<br>
 #include "llvm/IR/IntrinsicInst.h"<br>
 #include "llvm/IR/Intrinsics.h"<br>
 #include "llvm/IR/IntrinsicsAArch64.h"<br>
@@ -4038,7 +4039,7 @@ bool llvm::UpgradeDebugInfo(Module &M) {<br>
 /// returns true if module is modified.<br>
 static bool UpgradeRetainReleaseMarker(Module &M) {<br>
   bool Changed = false;<br>
-  const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";<br>
+  const char *MarkerKey = objcarc::getRVMarkerModuleFlagStr();<br>
   NamedMDNode *ModRetainReleaseMarker = M.getNamedMetadata(MarkerKey);<br>
   if (ModRetainReleaseMarker) {<br>
     MDNode *Op = ModRetainReleaseMarker->getOperand(0);<br>
<br>
diff  --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp<br>
index 6b33c03d66b70..6666d74ecabb3 100644<br>
--- a/llvm/lib/IR/Instructions.cpp<br>
+++ b/llvm/lib/IR/Instructions.cpp<br>
@@ -437,6 +437,35 @@ CallBase::BundleOpInfo &CallBase::getBundleOpInfoForOperand(unsigned OpIdx) {<br>
   return *Current;<br>
 }<br>
<br>
+CallBase *CallBase::addOperandBundle(CallBase *CB, uint32_t ID,<br>
+                                     OperandBundleDef OB,<br>
+                                     Instruction *InsertPt) {<br>
+  if (CB->getOperandBundle(ID))<br>
+    return CB;<br>
+<br>
+  SmallVector<OperandBundleDef, 1> Bundles;<br>
+  CB->getOperandBundlesAsDefs(Bundles);<br>
+  Bundles.push_back(OB);<br>
+  return Create(CB, Bundles, InsertPt);<br>
+}<br>
+<br>
+CallBase *CallBase::removeOperandBundle(CallBase *CB, uint32_t ID,<br>
+                                        Instruction *InsertPt) {<br>
+  SmallVector<OperandBundleDef, 1> Bundles;<br>
+  bool CreateNew = false;<br>
+<br>
+  for (unsigned I = 0, E = CB->getNumOperandBundles(); I != E; ++I) {<br>
+    auto Bundle = CB->getOperandBundleAt(I);<br>
+    if (Bundle.getTagID() == ID) {<br>
+      CreateNew = true;<br>
+      continue;<br>
+    }<br>
+    Bundles.emplace_back(Bundle);<br>
+  }<br>
+<br>
+  return CreateNew ? Create(CB, Bundles, InsertPt) : CB;<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 //                        CallInst Implementation<br>
 //===----------------------------------------------------------------------===//<br>
<br>
diff  --git a/llvm/lib/IR/LLVMContext.cpp b/llvm/lib/IR/LLVMContext.cpp<br>
index f554c54196bed..79002fb1b1bc7 100644<br>
--- a/llvm/lib/IR/LLVMContext.cpp<br>
+++ b/llvm/lib/IR/LLVMContext.cpp<br>
@@ -78,6 +78,12 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {<br>
          "gc-transition operand bundle id drifted!");<br>
   (void)GCLiveEntry;<br>
<br>
+  auto *ClangAttachedCall =<br>
+      pImpl->getOrInsertBundleTag("clang.arc.attachedcall");<br>
+  assert(ClangAttachedCall->second == LLVMContext::OB_clang_arc_attachedcall &&<br>
+         "clang.arc.attachedcall operand bundle id drifted!");<br>
+  (void)ClangAttachedCall;<br>
+<br>
   SyncScope::ID SingleThreadSSID =<br>
       pImpl->getOrInsertSyncScopeID("singlethread");<br>
   assert(SingleThreadSSID == SyncScope::SingleThread &&<br>
<br>
diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp<br>
index f8db3b74dbb48..47bfbfb19524b 100644<br>
--- a/llvm/lib/IR/Verifier.cpp<br>
+++ b/llvm/lib/IR/Verifier.cpp<br>
@@ -3187,7 +3187,8 @@ void Verifier::visitCallBase(CallBase &Call) {<br>
   // and at most one "preallocated" operand bundle.<br>
   bool FoundDeoptBundle = false, FoundFuncletBundle = false,<br>
        FoundGCTransitionBundle = false, FoundCFGuardTargetBundle = false,<br>
-       FoundPreallocatedBundle = false, FoundGCLiveBundle = false;;<br>
+       FoundPreallocatedBundle = false, FoundGCLiveBundle = false,<br>
+       FoundAttachedCallBundle = false;<br>
   for (unsigned i = 0, e = Call.getNumOperandBundles(); i < e; ++i) {<br>
     OperandBundleUse BU = Call.getOperandBundleAt(i);<br>
     uint32_t Tag = BU.getTagID();<br>
@@ -3228,9 +3229,19 @@ void Verifier::visitCallBase(CallBase &Call) {<br>
       Assert(!FoundGCLiveBundle, "Multiple gc-live operand bundles",<br>
              Call);<br>
       FoundGCLiveBundle = true;<br>
+    } else if (Tag == LLVMContext::OB_clang_arc_attachedcall) {<br>
+      Assert(!FoundAttachedCallBundle,<br>
+             "Multiple \"clang.arc.attachedcall\" operand bundles", Call);<br>
+      FoundAttachedCallBundle = true;<br>
     }<br>
   }<br>
<br>
+  if (FoundAttachedCallBundle)<br>
+    Assert(FTy->getReturnType()->isPointerTy(),<br>
+           "a call with operand bundle \"clang.arc.attachedcall\" must call a "<br>
+           "function returning a pointer",<br>
+           Call);<br>
+<br>
   // Verify that each inlinable callsite of a debug-info-bearing function in a<br>
   // debug-info-bearing function has a debug location attached to it. Failure to<br>
   // do so causes assertion failures when the inliner sets up inline scope info.<br>
<br>
diff  --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
index 703045412302f..3cc809eb255c3 100644<br>
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp<br>
@@ -29,6 +29,7 @@<br>
 #include "llvm/ADT/StringRef.h"<br>
 #include "llvm/ADT/Triple.h"<br>
 #include "llvm/ADT/Twine.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/Analysis/VectorUtils.h"<br>
 #include "llvm/CodeGen/CallingConvLower.h"<br>
 #include "llvm/CodeGen/MachineBasicBlock.h"<br>
@@ -5711,11 +5712,12 @@ AArch64TargetLowering::LowerCall(CallLoweringInfo &CLI,<br>
   }<br>
<br>
   unsigned CallOpc = AArch64ISD::CALL;<br>
-  // Calls marked with "rv_marker" are special. They should be expanded to the<br>
-  // call, directly followed by a special marker sequence. Use the CALL_RVMARKER<br>
-  // to do that.<br>
-  if (CLI.CB && CLI.CB->hasRetAttr("rv_marker")) {<br>
-    assert(!IsTailCall && "tail calls cannot be marked with rv_marker");<br>
+  // Calls with operand bundle "clang.arc.attachedcall" are special. They should<br>
+  // be expanded to the call, directly followed by a special marker sequence.<br>
+  // Use the CALL_RVMARKER to do that.<br>
+  if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB)) {<br>
+    assert(!IsTailCall &&<br>
+           "tail calls cannot be marked with clang.arc.attachedcall");<br>
     CallOpc = AArch64ISD::CALL_RVMARKER;<br>
   }<br>
<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h b/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h<br>
index 258dc92408150..764dc5f927073 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h<br>
+++ b/llvm/lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h<br>
@@ -42,6 +42,7 @@ enum class ARCRuntimeEntryPointKind {<br>
   Autorelease,<br>
   StoreStrong,<br>
   RetainRV,<br>
+  ClaimRV,<br>
   RetainAutorelease,<br>
   RetainAutoreleaseRV,<br>
 };<br>
@@ -61,6 +62,7 @@ class ARCRuntimeEntryPoints {<br>
     Autorelease = nullptr;<br>
     StoreStrong = nullptr;<br>
     RetainRV = nullptr;<br>
+    ClaimRV = nullptr;<br>
     RetainAutorelease = nullptr;<br>
     RetainAutoreleaseRV = nullptr;<br>
   }<br>
@@ -85,6 +87,9 @@ class ARCRuntimeEntryPoints {<br>
     case ARCRuntimeEntryPointKind::RetainRV:<br>
       return getIntrinsicEntryPoint(RetainRV,<br>
                                 Intrinsic::objc_retainAutoreleasedReturnValue);<br>
+    case ARCRuntimeEntryPointKind::ClaimRV:<br>
+      return getIntrinsicEntryPoint(<br>
+          ClaimRV, Intrinsic::objc_unsafeClaimAutoreleasedReturnValue);<br>
     case ARCRuntimeEntryPointKind::RetainAutorelease:<br>
       return getIntrinsicEntryPoint(RetainAutorelease,<br>
                                     Intrinsic::objc_retainAutorelease);<br>
@@ -121,6 +126,9 @@ class ARCRuntimeEntryPoints {<br>
   /// Declaration for objc_retainAutoreleasedReturnValue().<br>
   Function *RetainRV = nullptr;<br>
<br>
+  /// Declaration for objc_unsafeClaimAutoreleasedReturnValue().<br>
+  Function *ClaimRV = nullptr;<br>
+<br>
   /// Declaration for objc_retainAutorelease().<br>
   Function *RetainAutorelease = nullptr;<br>
<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp<br>
index 970136392fdd9..06b12149f5971 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp<br>
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp<br>
@@ -14,7 +14,12 @@<br>
<br>
 #include "ObjCARC.h"<br>
 #include "llvm-c/Initialization.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
+#include "llvm/IR/IRBuilder.h"<br>
+#include "llvm/IR/InlineAsm.h"<br>
+#include "llvm/IR/Instructions.h"<br>
 #include "llvm/InitializePasses.h"<br>
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"<br>
<br>
 namespace llvm {<br>
   class PassRegistry;<br>
@@ -37,3 +42,91 @@ void llvm::initializeObjCARCOpts(PassRegistry &Registry) {<br>
 void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R) {<br>
   initializeObjCARCOpts(*unwrap(R));<br>
 }<br>
+<br>
+CallInst *objcarc::createCallInstWithColors(<br>
+    FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,<br>
+    Instruction *InsertBefore,<br>
+    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {<br>
+  FunctionType *FTy = Func.getFunctionType();<br>
+  Value *Callee = Func.getCallee();<br>
+  SmallVector<OperandBundleDef, 1> OpBundles;<br>
+<br>
+  if (!BlockColors.empty()) {<br>
+    const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;<br>
+    assert(CV.size() == 1 && "non-unique color for block!");<br>
+    Instruction *EHPad = CV.front()->getFirstNonPHI();<br>
+    if (EHPad->isEHPad())<br>
+      OpBundles.emplace_back("funclet", EHPad);<br>
+  }<br>
+<br>
+  return CallInst::Create(FTy, Callee, Args, OpBundles, NameStr, InsertBefore);<br>
+}<br>
+<br>
+std::pair<bool, bool><br>
+BundledRetainClaimRVs::insertAfterInvokes(Function &F, DominatorTree *DT) {<br>
+  bool Changed = false, CFGChanged = false;<br>
+<br>
+  for (BasicBlock &BB : F) {<br>
+    auto *I = dyn_cast<InvokeInst>(BB.getTerminator());<br>
+<br>
+    if (!I)<br>
+      continue;<br>
+<br>
+    if (!objcarc::hasAttachedCallOpBundle(I))<br>
+      continue;<br>
+<br>
+    BasicBlock *DestBB = I->getNormalDest();<br>
+<br>
+    if (!DestBB->getSinglePredecessor()) {<br>
+      assert(I->getSuccessor(0) == DestBB &&<br>
+             "the normal dest is expected to be the first successor");<br>
+      DestBB = SplitCriticalEdge(I, 0, CriticalEdgeSplittingOptions(DT));<br>
+      CFGChanged = true;<br>
+    }<br>
+<br>
+    // We don't have to call insertRVCallWithColors since DestBB is the normal<br>
+    // destination of the invoke.<br>
+    insertRVCall(&*DestBB->getFirstInsertionPt(), I);<br>
+    Changed = true;<br>
+  }<br>
+<br>
+  return std::make_pair(Changed, CFGChanged);<br>
+}<br>
+<br>
+CallInst *BundledRetainClaimRVs::insertRVCall(Instruction *InsertPt,<br>
+                                              CallBase *AnnotatedCall) {<br>
+  DenseMap<BasicBlock *, ColorVector> BlockColors;<br>
+  return insertRVCallWithColors(InsertPt, AnnotatedCall, BlockColors);<br>
+}<br>
+<br>
+CallInst *BundledRetainClaimRVs::insertRVCallWithColors(<br>
+    Instruction *InsertPt, CallBase *AnnotatedCall,<br>
+    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {<br>
+  IRBuilder<> Builder(InsertPt);<br>
+  bool IsRetainRV = objcarc::hasAttachedCallOpBundle(AnnotatedCall, true);<br>
+  Function *Func = EP.get(IsRetainRV ? ARCRuntimeEntryPointKind::RetainRV<br>
+                                     : ARCRuntimeEntryPointKind::ClaimRV);<br>
+  Type *ParamTy = Func->getArg(0)->getType();<br>
+  Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);<br>
+  auto *Call =<br>
+      createCallInstWithColors(Func, CallArg, "", InsertPt, BlockColors);<br>
+  RVCalls[Call] = AnnotatedCall;<br>
+  return Call;<br>
+}<br>
+<br>
+BundledRetainClaimRVs::~BundledRetainClaimRVs() {<br>
+  if (ContractPass) {<br>
+    // At this point, we know that the annotated calls can't be tail calls as<br>
+    // they are followed by marker instructions and retainRV/claimRV calls. Mark<br>
+    // them as notail, so that the backend knows these calls can't be tail<br>
+    // calls.<br>
+    for (auto P : RVCalls)<br>
+      if (auto *CI = dyn_cast<CallInst>(P.second))<br>
+        CI->setTailCallKind(CallInst::TCK_NoTail);<br>
+  } else {<br>
+    for (auto P : RVCalls)<br>
+      EraseInstruction(P.first);<br>
+  }<br>
+<br>
+  RVCalls.clear();<br>
+}<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h<br>
index 8227a8c6f75f0..1f9d76969bfd7 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h<br>
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h<br>
@@ -22,7 +22,10 @@<br>
 #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H<br>
 #define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H<br>
<br>
+#include "ARCRuntimeEntryPoints.h"<br>
+#include "llvm/Analysis/EHPersonalities.h"<br>
 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/Transforms/Utils/Local.h"<br>
<br>
 namespace llvm {<br>
@@ -87,6 +90,75 @@ void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList) {<br>
   }<br>
 }<br>
<br>
+static inline MDString *getRVInstMarker(Module &M) {<br>
+  const char *MarkerKey = getRVMarkerModuleFlagStr();<br>
+  return dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey));<br>
+}<br>
+<br>
+/// Create a call instruction with the correct funclet token. This should be<br>
+/// called instead of calling CallInst::Create directly unless the call is<br>
+/// going to be removed from the IR before WinEHPrepare.<br>
+CallInst *createCallInstWithColors(<br>
+    FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,<br>
+    Instruction *InsertBefore,<br>
+    const DenseMap<BasicBlock *, ColorVector> &BlockColors);<br>
+<br>
+class BundledRetainClaimRVs {<br>
+public:<br>
+  BundledRetainClaimRVs(ARCRuntimeEntryPoints &P, bool ContractPass)<br>
+      : EP(P), ContractPass(ContractPass) {}<br>
+  ~BundledRetainClaimRVs();<br>
+<br>
+  /// Insert a retainRV/claimRV call to the normal destination blocks of invokes<br>
+  /// with operand bundle "clang.arc.attachedcall". If the edge to the normal<br>
+  /// destination block is a critical edge, split it.<br>
+  std::pair<bool, bool> insertAfterInvokes(Function &F, DominatorTree *DT);<br>
+<br>
+  /// Insert a retainRV/claimRV call.<br>
+  CallInst *insertRVCall(Instruction *InsertPt, CallBase *AnnotatedCall);<br>
+<br>
+  /// Insert a retainRV/claimRV call with colors.<br>
+  CallInst *insertRVCallWithColors(<br>
+      Instruction *InsertPt, CallBase *AnnotatedCall,<br>
+      const DenseMap<BasicBlock *, ColorVector> &BlockColors);<br>
+<br>
+  /// See if an instruction is a bundled retainRV/claimRV call.<br>
+  bool contains(const Instruction *I) const {<br>
+    if (auto *CI = dyn_cast<CallInst>(I))<br>
+      return RVCalls.count(CI);<br>
+    return false;<br>
+  }<br>
+<br>
+  /// Remove a retainRV/claimRV call entirely.<br>
+  void eraseInst(CallInst *CI) {<br>
+    auto It = RVCalls.find(CI);<br>
+    if (It != RVCalls.end()) {<br>
+      // Remove call to @llvm.objc.clang.arc.noop.use.<br>
+      for (auto U = It->second->user_begin(), E = It->second->user_end(); U != E; ++U)<br>
+        if (auto *CI = dyn_cast<CallInst>(*U))<br>
+          if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) {<br>
+            CI->eraseFromParent();<br>
+            break;<br>
+          }<br>
+<br>
+      auto *NewCall = CallBase::removeOperandBundle(<br>
+          It->second, LLVMContext::OB_clang_arc_attachedcall, It->second);<br>
+      NewCall->copyMetadata(*It->second);<br>
+      It->second->replaceAllUsesWith(NewCall);<br>
+      It->second->eraseFromParent();<br>
+      RVCalls.erase(It);<br>
+    }<br>
+    EraseInstruction(CI);<br>
+  }<br>
+<br>
+private:<br>
+  /// A map of inserted retainRV/claimRV calls to annotated calls/invokes.<br>
+  DenseMap<CallInst *, CallBase *> RVCalls;<br>
+<br>
+  ARCRuntimeEntryPoints &EP;<br>
+  bool ContractPass;<br>
+};<br>
+<br>
 } // end namespace objcarc<br>
 } // end namespace llvm<br>
<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp<br>
index 86d161116e8c7..62161b5b6b40a 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp<br>
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp<br>
@@ -32,6 +32,7 @@<br>
 #include "llvm/ADT/Statistic.h"<br>
 #include "llvm/Analysis/AliasAnalysis.h"<br>
 #include "llvm/Analysis/EHPersonalities.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/IR/Dominators.h"<br>
 #include "llvm/IR/InlineAsm.h"<br>
 #include "llvm/IR/InstIterator.h"<br>
@@ -63,13 +64,12 @@ namespace {<br>
<br>
 class ObjCARCContract {<br>
   bool Changed;<br>
+  bool CFGChanged;<br>
   AAResults *AA;<br>
   DominatorTree *DT;<br>
   ProvenanceAnalysis PA;<br>
   ARCRuntimeEntryPoints EP;<br>
-<br>
-  /// A flag indicating whether this optimization pass should run.<br>
-  bool Run;<br>
+  BundledRetainClaimRVs *BundledInsts = nullptr;<br>
<br>
   /// The inline asm string to insert between calls and RetainRV calls to make<br>
   /// the optimization work on targets which need it.<br>
@@ -98,6 +98,7 @@ class ObjCARCContract {<br>
 public:<br>
   bool init(Module &M);<br>
   bool run(Function &F, AAResults *AA, DominatorTree *DT);<br>
+  bool hasCFGChanged() const { return CFGChanged; }<br>
 };<br>
<br>
 class ObjCARCContractLegacyPass : public FunctionPass {<br>
@@ -304,32 +305,6 @@ findRetainForStoreStrongContraction(Value *New, StoreInst *Store,<br>
   return Retain;<br>
 }<br>
<br>
-/// Create a call instruction with the correct funclet token. Should be used<br>
-/// instead of calling CallInst::Create directly.<br>
-static CallInst *<br>
-createCallInst(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,<br>
-               const Twine &NameStr, Instruction *InsertBefore,<br>
-               const DenseMap<BasicBlock *, ColorVector> &BlockColors) {<br>
-  SmallVector<OperandBundleDef, 1> OpBundles;<br>
-  if (!BlockColors.empty()) {<br>
-    const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->second;<br>
-    assert(CV.size() == 1 && "non-unique color for block!");<br>
-    Instruction *EHPad = CV.front()->getFirstNonPHI();<br>
-    if (EHPad->isEHPad())<br>
-      OpBundles.emplace_back("funclet", EHPad);<br>
-  }<br>
-<br>
-  return CallInst::Create(FTy, Func, Args, OpBundles, NameStr, InsertBefore);<br>
-}<br>
-<br>
-static CallInst *<br>
-createCallInst(FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr,<br>
-               Instruction *InsertBefore,<br>
-               const DenseMap<BasicBlock *, ColorVector> &BlockColors) {<br>
-  return createCallInst(Func.getFunctionType(), Func.getCallee(), Args, NameStr,<br>
-                        InsertBefore, BlockColors);<br>
-}<br>
-<br>
 /// Attempt to merge an objc_release with a store, load, and objc_retain to form<br>
 /// an objc_storeStrong. An objc_storeStrong:<br>
 ///<br>
@@ -411,7 +386,8 @@ void ObjCARCContract::tryToContractReleaseIntoStoreStrong(<br>
   if (Args[1]->getType() != I8X)<br>
     Args[1] = new BitCastInst(Args[1], I8X, "", Store);<br>
   Function *Decl = EP.get(ARCRuntimeEntryPointKind::StoreStrong);<br>
-  CallInst *StoreStrong = createCallInst(Decl, Args, "", Store, BlockColors);<br>
+  CallInst *StoreStrong =<br>
+      objcarc::createCallInstWithColors(Decl, Args, "", Store, BlockColors);<br>
   StoreStrong->setDoesNotThrow();<br>
   StoreStrong->setDebugLoc(Store->getDebugLoc());<br>
<br>
@@ -456,9 +432,14 @@ bool ObjCARCContract::tryToPeepholeInstruction(<br>
   case ARCInstKind::RetainRV:<br>
   case ARCInstKind::ClaimRV: {<br>
     // If we're compiling for a target which needs a special inline-asm<br>
-    // marker to do the return value optimization, insert it now.<br>
+    // marker to do the return value optimization and the retainRV/claimRV call<br>
+    // wasn't bundled with a call, insert the marker now.<br>
     if (!RVInstMarker)<br>
       return false;<br>
+<br>
+    if (BundledInsts->contains(Inst))<br>
+      return false;<br>
+<br>
     BasicBlock::iterator BBI = Inst->getIterator();<br>
     BasicBlock *InstParent = Inst->getParent();<br>
<br>
@@ -486,7 +467,7 @@ bool ObjCARCContract::tryToPeepholeInstruction(<br>
                          RVInstMarker->getString(),<br>
                          /*Constraints=*/"", /*hasSideEffects=*/true);<br>
<br>
-      createCallInst(IA, None, "", Inst, BlockColors);<br>
+      objcarc::createCallInstWithColors(IA, None, "", Inst, BlockColors);<br>
     }<br>
   decline_rv_optimization:<br>
     return false;<br>
@@ -525,6 +506,12 @@ bool ObjCARCContract::tryToPeepholeInstruction(<br>
     Inst->eraseFromParent();<br>
     return true;<br>
   default:<br>
+    if (auto *CI = dyn_cast<CallInst>(Inst))<br>
+      if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) {<br>
+        // Remove calls to @llvm.objc.clang.arc.noop.use(...).<br>
+        Changed = true;<br>
+        CI->eraseFromParent();<br>
+      }<br>
     return true;<br>
   }<br>
 }<br>
@@ -534,16 +521,10 @@ bool ObjCARCContract::tryToPeepholeInstruction(<br>
 //===----------------------------------------------------------------------===//<br>
<br>
 bool ObjCARCContract::init(Module &M) {<br>
-  // If nothing in the Module uses ARC, don't do anything.<br>
-  Run = ModuleHasARC(M);<br>
-  if (!Run)<br>
-    return false;<br>
-<br>
   EP.init(&M);<br>
<br>
   // Initialize RVInstMarker.<br>
-  const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker";<br>
-  RVInstMarker = dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey));<br>
+  RVInstMarker = getRVInstMarker(M);<br>
<br>
   return false;<br>
 }<br>
@@ -552,14 +533,16 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {<br>
   if (!EnableARCOpts)<br>
     return false;<br>
<br>
-  // If nothing in the Module uses ARC, don't do anything.<br>
-  if (!Run)<br>
-    return false;<br>
-<br>
-  Changed = false;<br>
+  Changed = CFGChanged = false;<br>
   AA = A;<br>
   DT = D;<br>
   PA.setAA(A);<br>
+  BundledRetainClaimRVs BRV(EP, true);<br>
+  BundledInsts = &BRV;<br>
+<br>
+  std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT);<br>
+  Changed |= R.first;<br>
+  CFGChanged |= R.second;<br>
<br>
   DenseMap<BasicBlock *, ColorVector> BlockColors;<br>
   if (F.hasPersonalityFn() &&<br>
@@ -584,6 +567,13 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {<br>
<br>
     LLVM_DEBUG(dbgs() << "Visiting: " << *Inst << "\n");<br>
<br>
+    if (auto *CI = dyn_cast<CallInst>(Inst))<br>
+      if (objcarc::hasAttachedCallOpBundle(CI)) {<br>
+        BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors);<br>
+        --I;<br>
+        Changed = true;<br>
+      }<br>
+<br>
     // First try to peephole Inst. If there is nothing further we can do in<br>
     // terms of undoing objc-arc-expand, process the next inst.<br>
     if (tryToPeepholeInstruction(F, Inst, I, TailOkForStoreStrongs,<br>
@@ -733,7 +723,6 @@ INITIALIZE_PASS_END(ObjCARCContractLegacyPass, "objc-arc-contract",<br>
 void ObjCARCContractLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {<br>
   AU.addRequired<AAResultsWrapperPass>();<br>
   AU.addRequired<DominatorTreeWrapperPass>();<br>
-  AU.setPreservesCFG();<br>
 }<br>
<br>
 Pass *llvm::createObjCARCContractPass() {<br>
@@ -757,9 +746,11 @@ PreservedAnalyses ObjCARCContractPass::run(Function &F,<br>
<br>
   bool Changed = OCAC.run(F, &AM.getResult<AAManager>(F),<br>
                           &AM.getResult<DominatorTreeAnalysis>(F));<br>
+  bool CFGChanged = OCAC.hasCFGChanged();<br>
   if (Changed) {<br>
     PreservedAnalyses PA;<br>
-    PA.preserveSet<CFGAnalyses>();<br>
+    if (!CFGChanged)<br>
+      PA.preserveSet<CFGAnalyses>();<br>
     return PA;<br>
   }<br>
   return PreservedAnalyses::all();<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp<br>
index 2043a7bfc8876..0769d466be93d 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp<br>
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp<br>
@@ -41,6 +41,7 @@<br>
 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"<br>
 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"<br>
 #include "llvm/Analysis/ObjCARCInstKind.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/IR/BasicBlock.h"<br>
 #include "llvm/IR/CFG.h"<br>
 #include "llvm/IR/Constant.h"<br>
@@ -483,6 +484,7 @@ namespace {<br>
   /// The main ARC optimization pass.<br>
 class ObjCARCOpt {<br>
   bool Changed;<br>
+  bool CFGChanged;<br>
   ProvenanceAnalysis PA;<br>
<br>
   /// A cache of references to runtime entry point constants.<br>
@@ -492,8 +494,7 @@ class ObjCARCOpt {<br>
   /// MDKind identifiers.<br>
   ARCMDKindCache MDKindCache;<br>
<br>
-  /// A flag indicating whether this optimization pass should run.<br>
-  bool Run;<br>
+  BundledRetainClaimRVs *BundledInsts = nullptr;<br>
<br>
   /// A flag indicating whether the optimization that removes or moves<br>
   /// retain/release pairs should be performed.<br>
@@ -573,6 +574,7 @@ class ObjCARCOpt {<br>
     void init(Module &M);<br>
     bool run(Function &F, AAResults &AA);<br>
     void releaseMemory();<br>
+    bool hasCFGChanged() const { return CFGChanged; }<br>
 };<br>
<br>
 /// The main ARC optimization pass.<br>
@@ -610,8 +612,6 @@ Pass *llvm::createObjCARCOptPass() { return new ObjCARCOptLegacyPass(); }<br>
 void ObjCARCOptLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const {<br>
   AU.addRequired<ObjCARCAAWrapperPass>();<br>
   AU.addRequired<AAResultsWrapperPass>();<br>
-  // ARC optimization doesn't currently split critical edges.<br>
-  AU.setPreservesCFG();<br>
 }<br>
<br>
 /// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is<br>
@@ -640,6 +640,9 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) {<br>
     }<br>
   }<br>
<br>
+  assert(!BundledInsts->contains(RetainRV) &&<br>
+         "a bundled retainRV's argument should be a call");<br>
+<br>
   // Turn it to a plain objc_retain.<br>
   Changed = true;<br>
   ++NumPeeps;<br>
@@ -661,6 +664,9 @@ bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall(<br>
     Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors,<br>
     Instruction *Inst, const Value *&Arg, ARCInstKind Class,<br>
     Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) {<br>
+  if (BundledInsts->contains(Inst))<br>
+    return false;<br>
+<br>
   // Must be in the same basic block.<br>
   assert(Inst->getParent() == AutoreleaseRV->getParent());<br>
<br>
@@ -844,6 +850,12 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) {<br>
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) {<br>
     Instruction *Inst = &*I++;<br>
<br>
+    if (auto *CI = dyn_cast<CallInst>(Inst))<br>
+      if (objcarc::hasAttachedCallOpBundle(CI)) {<br>
+        BundledInsts->insertRVCall(&*I, CI);<br>
+        Changed = true;<br>
+      }<br>
+<br>
     ARCInstKind Class = GetBasicARCInstKind(Inst);<br>
<br>
     // Skip this loop if this instruction isn't itself an ARC intrinsic.<br>
@@ -922,6 +934,11 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(<br>
   // We can delete this call if it takes an inert value.<br>
   SmallPtrSet<Value *, 1> VisitedPhis;<br>
<br>
+  if (BundledInsts->contains(Inst)) {<br>
+    UsedInThisFunction |= 1 << unsigned(Class);<br>
+    return;<br>
+  }<br>
+<br>
   if (IsNoopOnGlobal(Class))<br>
     if (isInertARCValue(Inst->getOperand(0), VisitedPhis)) {<br>
       if (!Inst->getType()->isVoidTy())<br>
@@ -1539,7 +1556,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst,<br>
     if (Ptr == Arg)<br>
       continue; // Handled above.<br>
     TopDownPtrState &S = MI->second;<br>
-    if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class))<br>
+    if (S.HandlePotentialAlterRefCount(Inst, Ptr, PA, Class, *BundledInsts))<br>
       continue;<br>
<br>
     S.HandlePotentialUse(Inst, Ptr, PA, Class);<br>
@@ -2340,7 +2357,7 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {<br>
     ++NumRets;<br>
     LLVM_DEBUG(dbgs() << "Erasing: " << *Retain << "\nErasing: " << *Autorelease<br>
                       << "\n");<br>
-    EraseInstruction(Retain);<br>
+    BundledInsts->eraseInst(Retain);<br>
     EraseInstruction(Autorelease);<br>
   }<br>
 }<br>
@@ -2373,11 +2390,6 @@ void ObjCARCOpt::init(Module &M) {<br>
   if (!EnableARCOpts)<br>
     return;<br>
<br>
-  // If nothing in the Module uses ARC, don't do anything.<br>
-  Run = ModuleHasARC(M);<br>
-  if (!Run)<br>
-    return;<br>
-<br>
   // Intuitively, objc_retain and others are nocapture, however in practice<br>
   // they are not, because they return their argument value. And objc_release<br>
   // calls finalizers which can have arbitrary side effects.<br>
@@ -2391,16 +2403,18 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {<br>
   if (!EnableARCOpts)<br>
     return false;<br>
<br>
-  // If nothing in the Module uses ARC, don't do anything.<br>
-  if (!Run)<br>
-    return false;<br>
-<br>
-  Changed = false;<br>
+  Changed = CFGChanged = false;<br>
+  BundledRetainClaimRVs BRV(EP, false);<br>
+  BundledInsts = &BRV;<br>
<br>
   LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()<br>
                     << " >>>"<br>
                        "\n");<br>
<br>
+  std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, nullptr);<br>
+  Changed |= R.first;<br>
+  CFGChanged |= R.second;<br>
+<br>
   PA.setAA(&AA);<br>
<br>
 #ifndef NDEBUG<br>
@@ -2465,9 +2479,11 @@ PreservedAnalyses ObjCARCOptPass::run(Function &F,<br>
   OCAO.init(*F.getParent());<br>
<br>
   bool Changed = OCAO.run(F, AM.getResult<AAManager>(F));<br>
+  bool CFGChanged = OCAO.hasCFGChanged();<br>
   if (Changed) {<br>
     PreservedAnalyses PA;<br>
-    PA.preserveSet<CFGAnalyses>();<br>
+    if (!CFGChanged)<br>
+      PA.preserveSet<CFGAnalyses>();<br>
     return PA;<br>
   }<br>
   return PreservedAnalyses::all();<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/PtrState.cpp b/llvm/lib/Transforms/ObjCARC/PtrState.cpp<br>
index 66fdca062b3d5..d10d5851d5ea0 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/PtrState.cpp<br>
+++ b/llvm/lib/Transforms/ObjCARC/PtrState.cpp<br>
@@ -11,6 +11,7 @@<br>
 #include "ObjCARC.h"<br>
 #include "llvm/Analysis/ObjCARCAnalysisUtils.h"<br>
 #include "llvm/Analysis/ObjCARCInstKind.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/IR/BasicBlock.h"<br>
 #include "llvm/IR/Instruction.h"<br>
 #include "llvm/IR/Instructions.h"<br>
@@ -276,6 +277,13 @@ void BottomUpPtrState::HandlePotentialUse(BasicBlock *BB, Instruction *Inst,<br>
       InsertAfter = skipDebugIntrinsics(InsertAfter);<br>
<br>
     InsertReverseInsertPt(&*InsertAfter);<br>
+<br>
+    // Don't insert anything between a call/invoke with operand bundle<br>
+    // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call<br>
+    // result.<br>
+    if (auto *CB = dyn_cast<CallBase>(Inst))<br>
+      if (objcarc::hasAttachedCallOpBundle(CB))<br>
+        SetCFGHazardAfflicted(true);<br>
   };<br>
<br>
   // Check for possible direct uses.<br>
@@ -366,10 +374,9 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache,<br>
   llvm_unreachable("Sequence unknown enum value");<br>
 }<br>
<br>
-bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,<br>
-                                                   const Value *Ptr,<br>
-                                                   ProvenanceAnalysis &PA,<br>
-                                                   ARCInstKind Class) {<br>
+bool TopDownPtrState::HandlePotentialAlterRefCount(<br>
+    Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA,<br>
+    ARCInstKind Class, const BundledRetainClaimRVs &BundledRVs) {<br>
   // Check for possible releases. Treat clang.arc.use as a releasing instruction<br>
   // to prevent sinking a retain past it.<br>
   if (!CanDecrementRefCount(Inst, Ptr, PA, Class) &&<br>
@@ -385,6 +392,12 @@ bool TopDownPtrState::HandlePotentialAlterRefCount(Instruction *Inst,<br>
     assert(!HasReverseInsertPts());<br>
     InsertReverseInsertPt(Inst);<br>
<br>
+    // Don't insert anything between a call/invoke with operand bundle<br>
+    // "clang.arc.attachedcall" and the retainRV/claimRV call that uses the call<br>
+    // result.<br>
+    if (BundledRVs.contains(Inst))<br>
+      SetCFGHazardAfflicted(true);<br>
+<br>
     // One call can't cause a transition from S_Retain to S_CanRelease<br>
     // and S_CanRelease to S_Use. If we've made the first transition,<br>
     // we're done.<br>
<br>
diff  --git a/llvm/lib/Transforms/ObjCARC/PtrState.h b/llvm/lib/Transforms/ObjCARC/PtrState.h<br>
index c102219b59c93..232db2bd33bc7 100644<br>
--- a/llvm/lib/Transforms/ObjCARC/PtrState.h<br>
+++ b/llvm/lib/Transforms/ObjCARC/PtrState.h<br>
@@ -31,6 +31,7 @@ class Value;<br>
 namespace objcarc {<br>
<br>
 class ARCMDKindCache;<br>
+class BundledRetainClaimRVs;<br>
 class ProvenanceAnalysis;<br>
<br>
 /// \enum Sequence<br>
@@ -201,7 +202,8 @@ struct TopDownPtrState : PtrState {<br>
                           ProvenanceAnalysis &PA, ARCInstKind Class);<br>
<br>
   bool HandlePotentialAlterRefCount(Instruction *Inst, const Value *Ptr,<br>
-                                    ProvenanceAnalysis &PA, ARCInstKind Class);<br>
+                                    ProvenanceAnalysis &PA, ARCInstKind Class,<br>
+                                    const BundledRetainClaimRVs &BundledRVs);<br>
 };<br>
<br>
 } // end namespace objcarc<br>
<br>
diff  --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp<br>
index de6be52adf216..045abefd4741c 100644<br>
--- a/llvm/lib/Transforms/Scalar/SCCP.cpp<br>
+++ b/llvm/lib/Transforms/Scalar/SCCP.cpp<br>
@@ -144,9 +144,8 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {<br>
   /// represented here for efficient lookup.<br>
   SmallPtrSet<Function *, 16> MRVFunctionsTracked;<br>
<br>
-  /// MustTailFunctions - Each function here is a callee of non-removable<br>
-  /// musttail call site.<br>
-  SmallPtrSet<Function *, 16> MustTailCallees;<br>
+  /// A list of functions whose return cannot be modified.<br>
+  SmallPtrSet<Function *, 16> MustPreserveReturnsInFunctions;<br>
<br>
   /// TrackingIncomingArguments - This is the set of functions for whose<br>
   /// arguments we make optimistic assumptions about and try to prove as<br>
@@ -238,16 +237,14 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {<br>
       TrackedRetVals.insert(std::make_pair(F, ValueLatticeElement()));<br>
   }<br>
<br>
-  /// AddMustTailCallee - If the SCCP solver finds that this function is called<br>
-  /// from non-removable musttail call site.<br>
-  void AddMustTailCallee(Function *F) {<br>
-    MustTailCallees.insert(F);<br>
+  /// Add function to the list of functions whose return cannot be modified.<br>
+  void addToMustPreserveReturnsInFunctions(Function *F) {<br>
+    MustPreserveReturnsInFunctions.insert(F);<br>
   }<br>
<br>
-  /// Returns true if the given function is called from non-removable musttail<br>
-  /// call site.<br>
-  bool isMustTailCallee(Function *F) {<br>
-    return MustTailCallees.count(F);<br>
+  /// Returns true if the return of the given function cannot be modified.<br>
+  bool mustPreserveReturn(Function *F) {<br>
+    return MustPreserveReturnsInFunctions.count(F);<br>
   }<br>
<br>
   void AddArgumentTrackedFunction(Function *F) {<br>
@@ -319,12 +316,6 @@ class SCCPSolver : public InstVisitor<SCCPSolver> {<br>
     return MRVFunctionsTracked;<br>
   }<br>
<br>
-  /// getMustTailCallees - Get the set of functions which are called<br>
-  /// from non-removable musttail call sites.<br>
-  const SmallPtrSet<Function *, 16> getMustTailCallees() {<br>
-    return MustTailCallees;<br>
-  }<br>
-<br>
   /// markOverdefined - Mark the specified value overdefined.  This<br>
   /// works with both scalars and structs.<br>
   void markOverdefined(Value *V) {<br>
@@ -1650,16 +1641,19 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) {<br>
   assert(Const && "Constant is nullptr here!");<br>
<br>
   // Replacing `musttail` instructions with constant breaks `musttail` invariant<br>
-  // unless the call itself can be removed<br>
-  CallInst *CI = dyn_cast<CallInst>(V);<br>
-  if (CI && CI->isMustTailCall() && !CI->isSafeToRemove()) {<br>
-    Function *F = CI->getCalledFunction();<br>
+  // unless the call itself can be removed.<br>
+  // Calls with "clang.arc.attachedcall" implicitly use the return value and<br>
+  // those uses cannot be updated with a constant.<br>
+  CallBase *CB = dyn_cast<CallBase>(V);<br>
+  if (CB && ((CB->isMustTailCall() && !CB->isSafeToRemove()) ||<br>
+             CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall))) {<br>
+    Function *F = CB->getCalledFunction();<br>
<br>
     // Don't zap returns of the callee<br>
     if (F)<br>
-      Solver.AddMustTailCallee(F);<br>
+      Solver.addToMustPreserveReturnsInFunctions(F);<br>
<br>
-    LLVM_DEBUG(dbgs() << "  Can\'t treat the result of musttail call : " << *CI<br>
+    LLVM_DEBUG(dbgs() << "  Can\'t treat the result of call " << *CB<br>
                       << " as a constant\n");<br>
     return false;<br>
   }<br>
@@ -1821,11 +1815,12 @@ static void findReturnsToZap(Function &F,<br>
   if (!Solver.isArgumentTrackedFunction(&F))<br>
     return;<br>
<br>
-  // There is a non-removable musttail call site of this function. Zapping<br>
-  // returns is not allowed.<br>
-  if (Solver.isMustTailCallee(&F)) {<br>
-    LLVM_DEBUG(dbgs() << "Can't zap returns of the function : " << F.getName()<br>
-                      << " due to present musttail call of it\n");<br>
+  if (Solver.mustPreserveReturn(&F)) {<br>
+    LLVM_DEBUG(<br>
+        dbgs()<br>
+        << "Can't zap returns of the function : " << F.getName()<br>
+        << " due to present musttail or \"clang.arc.attachedcall\" call of "<br>
+           "it\n");<br>
     return;<br>
   }<br>
<br>
<br>
diff  --git a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp<br>
index 9e7cccc884127..8cc649a8c1ed8 100644<br>
--- a/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp<br>
+++ b/llvm/lib/Transforms/Scalar/TailRecursionElimination.cpp<br>
@@ -247,7 +247,10 @@ static bool markTails(Function &F, bool &AllCallsAreTailCalls,<br>
           isa<PseudoProbeInst>(&I))<br>
         continue;<br>
<br>
-      bool IsNoTail = CI->isNoTailCall() || CI->hasOperandBundles();<br>
+      // Special-case operand bundle "clang.arc.attachedcall".<br>
+      bool IsNoTail =<br>
+          CI->isNoTailCall() || CI->hasOperandBundlesOtherThan(<br>
+                                    LLVMContext::OB_clang_arc_attachedcall);<br>
<br>
       if (!IsNoTail && CI->doesNotAccessMemory()) {<br>
         // A call to a readnone function whose arguments are all things computed<br>
<br>
diff  --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp<br>
index 3026342cc4a6b..5f75ead1247bb 100644<br>
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp<br>
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp<br>
@@ -27,8 +27,9 @@<br>
 #include "llvm/Analysis/CaptureTracking.h"<br>
 #include "llvm/Analysis/EHPersonalities.h"<br>
 #include "llvm/Analysis/InstructionSimplify.h"<br>
+#include "llvm/Analysis/ObjCARCAnalysisUtils.h"<br>
+#include "llvm/Analysis/ObjCARCUtil.h"<br>
 #include "llvm/Analysis/ProfileSummaryInfo.h"<br>
-#include "llvm/Transforms/Utils/Local.h"<br>
 #include "llvm/Analysis/ValueTracking.h"<br>
 #include "llvm/Analysis/VectorUtils.h"<br>
 #include "llvm/IR/Argument.h"<br>
@@ -61,6 +62,7 @@<br>
 #include "llvm/Support/ErrorHandling.h"<br>
 #include "llvm/Transforms/Utils/AssumeBundleBuilder.h"<br>
 #include "llvm/Transforms/Utils/Cloning.h"<br>
+#include "llvm/Transforms/Utils/Local.h"<br>
 #include "llvm/Transforms/Utils/ValueMapper.h"<br>
 #include <algorithm><br>
 #include <cassert><br>
@@ -1650,6 +1652,99 @@ void llvm::updateProfileCallee(<br>
   }<br>
 }<br>
<br>
+/// An operand bundle "clang.arc.attachedcall" on a call indicates the call<br>
+/// result is implicitly consumed by a call to retainRV or claimRV immediately<br>
+/// after the call. This function inlines the retainRV/claimRV calls.<br>
+///<br>
+/// There are three cases to consider:<br>
+///<br>
+/// 1. If there is a call to autoreleaseRV that takes a pointer to the returned<br>
+///    object in the callee return block, the autoreleaseRV call and the<br>
+///    retainRV/claimRV call in the caller cancel out. If the call in the caller<br>
+///    is a claimRV call, a call to objc_release is emitted.<br>
+///<br>
+/// 2. If there is a call in the callee return block that doesn't have operand<br>
+///    bundle "clang.arc.attachedcall", the operand bundle on the original call<br>
+///    is transferred to the call in the callee.<br>
+///<br>
+/// 3. Otherwise, a call to objc_retain is inserted if the call in the caller is<br>
+///    a retainRV call.<br>
+static void<br>
+inlineRetainOrClaimRVCalls(CallBase &CB,<br>
+                           const SmallVectorImpl<ReturnInst *> &Returns) {<br>
+  Module *Mod = CB.getModule();<br>
+  bool IsRetainRV = objcarc::hasAttachedCallOpBundle(&CB, true),<br>
+       IsClaimRV = !IsRetainRV;<br>
+<br>
+  for (auto *RI : Returns) {<br>
+    Value *RetOpnd = objcarc::GetRCIdentityRoot(RI->getOperand(0));<br>
+    BasicBlock::reverse_iterator I = ++(RI->getIterator().getReverse());<br>
+    BasicBlock::reverse_iterator EI = RI->getParent()->rend();<br>
+    bool InsertRetainCall = IsRetainRV;<br>
+    IRBuilder<> Builder(RI->getContext());<br>
+<br>
+    // Walk backwards through the basic block looking for either a matching<br>
+    // autoreleaseRV call or an unannotated call.<br>
+    for (; I != EI;) {<br>
+      auto CurI = I++;<br>
+<br>
+      // Ignore casts.<br>
+      if (isa<CastInst>(*CurI))<br>
+        continue;<br>
+<br>
+      if (auto *II = dyn_cast<IntrinsicInst>(&*CurI)) {<br>
+        if (II->getIntrinsicID() == Intrinsic::objc_autoreleaseReturnValue &&<br>
+            II->hasNUses(0) &&<br>
+            objcarc::GetRCIdentityRoot(II->getOperand(0)) == RetOpnd) {<br>
+          // If we've found a matching authoreleaseRV call:<br>
+          // - If claimRV is attached to the call, insert a call to objc_release<br>
+          //   and erase the autoreleaseRV call.<br>
+          // - If retainRV is attached to the call, just erase the autoreleaseRV<br>
+          //   call.<br>
+          if (IsClaimRV) {<br>
+            Builder.SetInsertPoint(II);<br>
+            Function *IFn =<br>
+                Intrinsic::getDeclaration(Mod, Intrinsic::objc_release);<br>
+            Value *BC =<br>
+                Builder.CreateBitCast(RetOpnd, IFn->getArg(0)->getType());<br>
+            Builder.CreateCall(IFn, BC, "");<br>
+          }<br>
+          II->eraseFromParent();<br>
+          InsertRetainCall = false;<br>
+        }<br>
+      } else if (auto *CI = dyn_cast<CallInst>(&*CurI)) {<br>
+        if (objcarc::GetRCIdentityRoot(CI) == RetOpnd &&<br>
+            !objcarc::hasAttachedCallOpBundle(CI)) {<br>
+          // If we've found an unannotated call that defines RetOpnd, add a<br>
+          // "clang.arc.attachedcall" operand bundle.<br>
+          Value *BundleArgs[] = {ConstantInt::get(<br>
+              Builder.getInt64Ty(),<br>
+              objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};<br>
+          OperandBundleDef OB("clang.arc.attachedcall", BundleArgs);<br>
+          auto *NewCall = CallBase::addOperandBundle(<br>
+              CI, LLVMContext::OB_clang_arc_attachedcall, OB, CI);<br>
+          NewCall->copyMetadata(*CI);<br>
+          CI->replaceAllUsesWith(NewCall);<br>
+          CI->eraseFromParent();<br>
+          InsertRetainCall = false;<br>
+        }<br>
+      }<br>
+<br>
+      break;<br>
+    }<br>
+<br>
+    if (InsertRetainCall) {<br>
+      // The retainRV is attached to the call and we've failed to find a<br>
+      // matching autoreleaseRV or an annotated call in the callee. Emit a call<br>
+      // to objc_retain.<br>
+      Builder.SetInsertPoint(RI);<br>
+      Function *IFn = Intrinsic::getDeclaration(Mod, Intrinsic::objc_retain);<br>
+      Value *BC = Builder.CreateBitCast(RetOpnd, IFn->getArg(0)->getType());<br>
+      Builder.CreateCall(IFn, BC, "");<br>
+    }<br>
+  }<br>
+}<br>
+<br>
 /// This function inlines the called function into the basic block of the<br>
 /// caller. This returns false if it is not possible to inline this call.<br>
 /// The program is still in a well defined state if this occurs though.<br>
@@ -1687,6 +1782,8 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,<br>
       // ... and "funclet" operand bundles.<br>
       if (Tag == LLVMContext::OB_funclet)<br>
         continue;<br>
+      if (Tag == LLVMContext::OB_clang_arc_attachedcall)<br>
+        continue;<br>
<br>
       return InlineResult::failure("unsupported operand bundle");<br>
     }<br>
@@ -1853,6 +1950,10 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,<br>
     // Remember the first block that is newly cloned over.<br>
     FirstNewBlock = LastBlock; ++FirstNewBlock;<br>
<br>
+    // Insert retainRV/clainRV runtime calls.<br>
+    if (objcarc::hasAttachedCallOpBundle(&CB))<br>
+      inlineRetainOrClaimRVCalls(CB, Returns);<br>
+<br>
     if (IFI.CallerBFI != nullptr && IFI.CalleeBFI != nullptr)<br>
       // Update the BFI of blocks cloned into the caller.<br>
       updateCallerBFI(OrigBB, VMap, IFI.CallerBFI, IFI.CalleeBFI,<br>
<br>
diff  --git a/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll<br>
index f22fcbeb271ed..cb7a3ee7eb714 100644<br>
--- a/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll<br>
+++ b/llvm/test/Bitcode/operand-bundles-bc-analyzer.ll<br>
@@ -9,6 +9,7 @@<br>
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG<br>
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG<br>
 ; CHECK-NEXT:    <OPERAND_BUNDLE_TAG<br>
+; CHECK-NEXT:    <OPERAND_BUNDLE_TAG<br>
 ; CHECK-NEXT:  </OPERAND_BUNDLE_TAGS_BLOCK<br>
<br>
 ; CHECK:   <FUNCTION_BLOCK<br>
<br>
diff  --git a/llvm/test/CodeGen/AArch64/call-rv-marker.ll b/llvm/test/CodeGen/AArch64/call-rv-marker.ll<br>
index 245d2c854c342..3b5ab40839b57 100644<br>
--- a/llvm/test/CodeGen/AArch64/call-rv-marker.ll<br>
+++ b/llvm/test/CodeGen/AArch64/call-rv-marker.ll<br>
@@ -33,7 +33,7 @@ define dso_local i8* @rv_marker_1() {<br>
 ; GISEL-NOT:       mov x29, x29<br>
 ;<br>
 entry:<br>
-  %call = call "rv_marker" i8* @foo1()<br>
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]<br>
   ret i8* %call<br>
 }<br>
<br>
@@ -49,7 +49,7 @@ define dso_local void @rv_marker_2_select(i32 %c) {<br>
 entry:<br>
   %tobool.not = icmp eq i32 %c, 0<br>
   %.sink = select i1 %tobool.not, i32 2, i32 1<br>
-  %call1 = call "rv_marker" i8* @foo0(i32 %.sink)<br>
+  %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i64 0) ]<br>
   tail call void @foo2(i8* %call1)<br>
   ret void<br>
 }<br>
@@ -61,7 +61,7 @@ define dso_local void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_<br>
 ; SELDAG-NEXT:   mov x29, x29<br>
 ;<br>
 entry:<br>
-  %call = call "rv_marker" i8* @foo1()<br>
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]<br>
   invoke void @objc_object(i8* %call) #5<br>
           to label %invoke.cont unwind label %lpad<br>
<br>
@@ -87,7 +87,7 @@ entry:<br>
   %s = alloca %struct.S, align 1<br>
   %0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0<br>
   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2<br>
-  %call = invoke "rv_marker" i8* @foo1()<br>
+  %call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]<br>
           to label %invoke.cont unwind label %lpad<br>
<br>
 invoke.cont:                                      ; preds = %entry<br>
@@ -127,12 +127,12 @@ define dso_local i8* @rv_marker_5_indirect_call() {<br>
 ;<br>
 entry:<br>
   %0 = load i8* ()*, i8* ()** @fptr, align 8<br>
-  %call = call "rv_marker" i8* %0()<br>
+  %call = call i8* %0() [ "clang.arc.attachedcall"(i64 0) ]<br>
   tail call void @foo2(i8* %call)<br>
   ret i8* %call<br>
 }<br>
<br>
-declare void @foo(i64, i64, i64)<br>
+declare i8* @foo(i64, i64, i64)<br>
<br>
 define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {<br>
 ; CHECK-LABEL: rv_marker_multiarg<br>
@@ -142,7 +142,7 @@ define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {<br>
 ; CHECK-NEXT:   bl  foo<br>
 ; SELDAG-NEXT:  mov x29, x29<br>
 ; GISEL-NOT:    mov x29, x29<br>
-  call "rv_marker" void @foo(i64 %c, i64 %b, i64 %a)<br>
+  call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i64 0) ]<br>
   ret void<br>
 }<br>
<br>
<br>
diff  --git a/llvm/test/Transforms/DeadArgElim/deadretval.ll b/llvm/test/Transforms/DeadArgElim/deadretval.ll<br>
index 5f3817c6728dd..f3b343745e4d2 100644<br>
--- a/llvm/test/Transforms/DeadArgElim/deadretval.ll<br>
+++ b/llvm/test/Transforms/DeadArgElim/deadretval.ll<br>
@@ -1,4 +1,8 @@<br>
-; RUN: opt < %s -deadargelim -S | not grep DEAD<br>
+; RUN: opt < %s -deadargelim -S | FileCheck %s<br>
+<br>
+@g0 = global i8 0, align 8<br>
+<br>
+; CHECK-NOT: DEAD<br>
<br>
 ; Dead arg only used by dead retval<br>
 define internal i32 @test(i32 %DEADARG) {<br>
@@ -16,3 +20,22 @@ define i32 @test3() {<br>
         ret i32 %Y<br>
 }<br>
<br>
+; The callee function's return type shouldn't be changed if the call result is<br>
+; used.<br>
+<br>
+; CHECK-LABEL: define internal i8* @callee4()<br>
+<br>
+define internal i8* @callee4(i8* %a0) {<br>
+  ret i8* @g0;<br>
+}<br>
+<br>
+declare void @llvm.objc.clang.arc.noop.use(...)<br>
+<br>
+; CHECK-LABEL: define i8* @test4(<br>
+; CHECK: tail call i8* @callee4() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+define i8* @test4() {<br>
+  %call = tail call i8* @callee4(i8* @g0) [ "clang.arc.attachedcall"(i64 0) ]<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)<br>
+  ret i8* @g0<br>
+}<br>
<br>
diff  --git a/llvm/test/Transforms/Inline/inline-retainRV-call.ll b/llvm/test/Transforms/Inline/inline-retainRV-call.ll<br>
new file mode 100644<br>
index 0000000000000..f8ac2154f9339<br>
--- /dev/null<br>
+++ b/llvm/test/Transforms/Inline/inline-retainRV-call.ll<br>
@@ -0,0 +1,175 @@<br>
+; RUN: opt < %s -inline -S | FileCheck %s<br>
+<br>
+@g0 = global i8* null, align 8<br>
+declare i8* @foo0()<br>
+<br>
+define i8* @callee0_autoreleaseRV() {<br>
+  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)<br>
+  ret i8* %call<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test0_autoreleaseRV(<br>
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+define void @test0_autoreleaseRV() {<br>
+  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(<br>
+; CHECK: %[[CALL:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK: call void @llvm.objc.release(i8* %[[CALL]])<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test0_claimRV_autoreleaseRV() {<br>
+  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test1_autoreleaseRV(<br>
+; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+define void @test1_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
+entry:<br>
+  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]<br>
+          to label %invoke.cont unwind label %lpad<br>
+<br>
+invoke.cont:<br>
+  ret void<br>
+<br>
+lpad:<br>
+  %0 = landingpad { i8*, i32 }<br>
+          cleanup<br>
+  resume { i8*, i32 } undef<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(<br>
+; CHECK: %[[INVOKE:.*]] = invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK: call void @llvm.objc.release(i8* %[[INVOKE]])<br>
+; CHECK-NEXT: br<br>
+<br>
+define void @test1_claimRV_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
+entry:<br>
+  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]<br>
+          to label %invoke.cont unwind label %lpad<br>
+<br>
+invoke.cont:<br>
+  ret void<br>
+<br>
+lpad:<br>
+  %0 = landingpad { i8*, i32 }<br>
+          cleanup<br>
+  resume { i8*, i32 } undef<br>
+}<br>
+<br>
+define i8* @callee1_no_autoreleaseRV() {<br>
+  %call = call i8* @foo0()<br>
+  ret i8* %call<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test2_no_autoreleaseRV(<br>
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test2_no_autoreleaseRV() {<br>
+  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(<br>
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 1) ]<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test2_claimRV_no_autoreleaseRV() {<br>
+  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test3_no_autoreleaseRV(<br>
+; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+define void @test3_no_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
+entry:<br>
+  %call = invoke i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]<br>
+          to label %invoke.cont unwind label %lpad<br>
+<br>
+invoke.cont:<br>
+  ret void<br>
+<br>
+lpad:<br>
+  %0 = landingpad { i8*, i32 }<br>
+          cleanup<br>
+  resume { i8*, i32 } undef<br>
+}<br>
+<br>
+define i8* @callee2_nocall() {<br>
+  %1 = load i8*, i8** @g0, align 8<br>
+  ret i8* %1<br>
+}<br>
+<br>
+; Check that a call to @llvm.objc.retain is inserted if there is no matching<br>
+; autoreleaseRV call or a call.<br>
+<br>
+; CHECK-LABEL: define void @test4_nocall(<br>
+; CHECK: %[[V0:.*]] = load i8*, i8** @g0,<br>
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test4_nocall() {<br>
+  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test4_claimRV_nocall(<br>
+; CHECK: %[[V0:.*]] = load i8*, i8** @g0,<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test4_claimRV_nocall() {<br>
+  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 1) ]<br>
+  ret void<br>
+}<br>
+<br>
+; Check that a call to @llvm.objc.retain is inserted if call to @foo already has<br>
+; the attribute. I'm not sure this will happen in practice.<br>
+<br>
+define i8* @callee3_marker() {<br>
+  %1 = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret i8* %1<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test5(<br>
+; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test5() {<br>
+  %call = call i8* @callee3_marker() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+; Don't pair up an autoreleaseRV in the callee and an retainRV in the caller<br>
+; if there is an instruction between the ret instruction and the call to<br>
+; autoreleaseRV that isn't a cast instruction.<br>
+<br>
+define i8* @callee0_autoreleaseRV2() {<br>
+  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)<br>
+  store i8* null, i8** @g0<br>
+  ret i8* %call<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test6(<br>
+; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V0]])<br>
+; CHECK: store i8* null, i8** @g0, align 8<br>
+; CHECK: call i8* @llvm.objc.retain(i8* %[[V0]])<br>
+; CHECK-NEXT: ret void<br>
+<br>
+define void @test6() {<br>
+  %call = call i8* @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+declare i8* @llvm.objc.autoreleaseReturnValue(i8*)<br>
+declare i32 @__gxx_personality_v0(...)<br>
<br>
diff  --git a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll<br>
index c0d6e0033dda2..c40f411c9fb75 100644<br>
--- a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll<br>
+++ b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll<br>
@@ -10,6 +10,16 @@<br>
 ;   }<br>
 ; }<br>
<br>
+; CHECK-LABEL: define void @"\01?g@@YAXXZ"()<br>
+; CHECK-LABEL: catch<br>
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]<br>
+<br>
+; CHECK-LABEL: catch.1<br>
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]<br>
+<br>
+; CHECK-LABEL: invoke.cont<br>
+; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}<br>
+<br>
 define void @"\01?g@@YAXXZ"() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {<br>
 entry:<br>
   %call = invoke i8* @"\01?f@@YAPAUobjc_object@@XZ"()<br>
@@ -40,23 +50,41 @@ invoke.cont:                                      ; preds = %entry<br>
   ret void<br>
 }<br>
<br>
+; CHECK-LABEL: define dso_local void @"?test_attr_claimRV@@YAXXZ"()<br>
+; CHECK: %[[CALL4:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "clang.arc.attachedcall"(i64 1) ]<br>
+; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL4]])<br>
+<br>
+; CHECK: %[[V1:.*]] = cleanuppad<br>
+; CHECK: %[[CALL:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "funclet"(token %[[V1]]), "clang.arc.attachedcall"(i64 1) ]<br>
+; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]]) [ "funclet"(token %[[V1]]) ]<br>
+<br>
+define dso_local void @"?test_attr_claimRV@@YAXXZ"() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {<br>
+entry:<br>
+  invoke void @"?foo@@YAXXZ"()<br>
+          to label %invoke.cont unwind label %ehcleanup<br>
+<br>
+invoke.cont:                                      ; preds = %entry<br>
+  %call.i4 = tail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "clang.arc.attachedcall"(i64 1) ]<br>
+  ret void<br>
+<br>
+ehcleanup:                                        ; preds = %entry<br>
+  %0 = cleanuppad within none []<br>
+  %call.i = call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "funclet"(token %0), "clang.arc.attachedcall"(i64 1) ]<br>
+  cleanupret from %0 unwind to caller<br>
+}<br>
+<br>
 declare i8* @"\01?f@@YAPAUobjc_object@@XZ"()<br>
<br>
 declare i32 @__CxxFrameHandler3(...)<br>
<br>
+declare void @"?foo@@YAXXZ"()<br>
+declare i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"()<br>
+<br>
 declare dllimport i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)<br>
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)<br>
<br>
 declare dllimport void @llvm.objc.release(i8*)<br>
<br>
 !llvm.module.flags = !{!0}<br>
<br>
 !0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"movl\09%ebp, %ebp\09\09// marker for objc_retainAutoreleaseReturnValue"}<br>
-<br>
-; CHECK-LABEL: catch<br>
-; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]<br>
-<br>
-; CHECK-LABEL: catch.1<br>
-; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""() [ "funclet"(token %1) ]<br>
-<br>
-; CHECK-LABEL: invoke.cont<br>
-; CHECK: call void asm sideeffect "movl{{.*}}%ebp, %ebp{{.*}}", ""(){{$}}<br>
<br>
diff  --git a/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll<br>
new file mode 100644<br>
index 0000000000000..3a817327c3638<br>
--- /dev/null<br>
+++ b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll<br>
@@ -0,0 +1,63 @@<br>
+; RUN: opt -objc-arc-contract -S < %s | FileCheck %s<br>
+; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s<br>
+<br>
+; CHECK-LABEL: define void @test0() {<br>
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL]])<br>
+<br>
+define void @test0() {<br>
+  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL: define void @test1() {<br>
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]<br>
+; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]])<br>
+<br>
+define void @test1() {<br>
+  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]<br>
+  ret void<br>
+}<br>
+<br>
+; CHECK-LABEL:define i8* @test2(<br>
+; CHECK: %[[CALL1:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+; CHECK: %[[V0:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])<br>
+; CHECK-NEXT: br<br>
+<br>
+; CHECK: %[[CALL3:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+; CHECK: %[[V2:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL3]])<br>
+; CHECK-NEXT: br<br>
+<br>
+; CHECK: %[[RETVAL:.*]] = phi i8* [ %[[V0]], {{.*}} ], [ %[[V2]], {{.*}} ]<br>
+; CHECK: ret i8* %[[RETVAL]]<br>
+<br>
+define i8* @test2(i1 zeroext %b) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {<br>
+entry:<br>
+  br i1 %b, label %if.then, label %if.end<br>
+<br>
+if.then:<br>
+  %call1 = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+          to label %cleanup unwind label %lpad<br>
+<br>
+lpad:<br>
+  %0 = landingpad { i8*, i32 }<br>
+          cleanup<br>
+  resume { i8*, i32 } undef<br>
+<br>
+if.end:<br>
+  %call3 = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]<br>
+          to label %cleanup unwind label %lpad<br>
+<br>
+cleanup:<br>
+  %retval.0 = phi i8* [ %call1, %if.then ], [ %call3, %if.end ]<br>
+  ret i8* %retval.0<br>
+}<br>
+<br>
+declare i8* @foo()<br>
+declare i32 @__gxx_personality_v0(...)<br>
+<br>
+!llvm.module.flags = !{!0}<br>
+<br>
+!0 = !{i32 1, !"clang.arc.retainAutoreleasedReturnValueMarker", !"mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue"}<br>
<br>
diff  --git a/llvm/test/Transforms/ObjCARC/contract.ll b/llvm/test/Transforms/ObjCARC/contract.ll<br>
index d62fe221529e2..36f0a842d0e66 100644<br>
--- a/llvm/test/Transforms/ObjCARC/contract.ll<br>
+++ b/llvm/test/Transforms/ObjCARC/contract.ll<br>
@@ -227,7 +227,15 @@ define void @test13() {<br>
   ret void<br>
 }<br>
<br>
+; CHECK-LABEL: define void @test14(<br>
+; CHECK-NOT: clang.arc.noop.use<br>
+; CHECK: ret void<br>
+define void @test14(i8* %a, i8* %b) {<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %a, i8* %b) nounwind<br>
+  ret void<br>
+}<br>
<br>
 declare void @llvm.objc.clang.arc.use(...) nounwind<br>
+declare void @llvm.objc.clang.arc.noop.use(...) nounwind<br>
<br>
 ; CHECK: attributes [[NUW]] = { nounwind }<br>
<br>
diff  --git a/llvm/test/Transforms/ObjCARC/intrinsic-use.ll b/llvm/test/Transforms/ObjCARC/intrinsic-use.ll<br>
index 6f3815113d698..bd4ac2965fb34 100644<br>
--- a/llvm/test/Transforms/ObjCARC/intrinsic-use.ll<br>
+++ b/llvm/test/Transforms/ObjCARC/intrinsic-use.ll<br>
@@ -8,8 +8,10 @@ declare void @llvm.objc.release(i8*)<br>
 declare i8* @llvm.objc.autorelease(i8*)<br>
<br>
 declare void @llvm.objc.clang.arc.use(...)<br>
+declare void @llvm.objc.clang.arc.noop.use(...)<br>
<br>
 declare void @test0_helper(i8*, i8**)<br>
+declare void @can_release(i8*)<br>
<br>
 ; Ensure that we honor clang.arc.use as a use and don't miscompile<br>
 ; the reduced test case from <rdar://13195034>.<br>
@@ -108,6 +110,21 @@ entry:<br>
   ret void<br>
 }<br>
<br>
+; ARC optimizer should be able to safely remove the retain/release pair as the<br>
+; call to @llvm.objc.clang.arc.noop.use is a no-op.<br>
+<br>
+; CHECK-LABEL: define void @test_arc_noop_use(<br>
+; CHECK-NEXT:    call void @can_release(i8* %x)<br>
+; CHECK-NEXT:    call void (...) @llvm.objc.clang.arc.noop.use(<br>
+; CHECK-NEXT:    ret void<br>
+<br>
+define void @test_arc_noop_use(i8** %out, i8* %x) {<br>
+  call i8* @llvm.objc.retain(i8* %x)<br>
+  call void @can_release(i8* %x)<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %x)<br>
+  call void @llvm.objc.release(i8* %x), !clang.imprecise_release !0<br>
+  ret void<br>
+}<br>
<br>
 !0 = !{}<br>
<br>
<br>
diff  --git a/llvm/test/Transforms/ObjCARC/rv.ll b/llvm/test/Transforms/ObjCARC/rv.ll<br>
index f89e9f7e39d99..29017222ebb11 100644<br>
--- a/llvm/test/Transforms/ObjCARC/rv.ll<br>
+++ b/llvm/test/Transforms/ObjCARC/rv.ll<br>
@@ -11,6 +11,7 @@ declare i8* @llvm.objc.retainAutoreleaseReturnValue(i8*)<br>
 declare void @llvm.objc.autoreleasePoolPop(i8*)<br>
 declare void @llvm.objc.autoreleasePoolPush()<br>
 declare i8* @llvm.objc.retainBlock(i8*)<br>
+declare void @llvm.objc.clang.arc.noop.use(...)<br>
<br>
 declare i8* @objc_retainedObject(i8*)<br>
 declare i8* @objc_unretainedObject(i8*)<br>
@@ -452,6 +453,32 @@ bb1:<br>
   ret i8* %v3<br>
 }<br>
<br>
+; Remove operand bundle "clang.arc.attachedcall" and the autoreleaseRV call if the call<br>
+; is a tail call.<br>
+<br>
+; CHECK-LABEL: define i8* @test31(<br>
+; CHECK-NEXT: %[[CALL:.*]] = tail call i8* @returner()<br>
+; CHECK-NEXT: ret i8* %[[CALL]]<br>
+<br>
+define i8* @test31() {<br>
+  %call = tail call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)<br>
+  %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)<br>
+  ret i8* %1<br>
+}<br>
+<br>
+; CHECK-LABEL: define i8* @test32(<br>
+; CHECK: %[[CALL:.*]] = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK: call void (...) @llvm.objc.clang.arc.noop.use(i8* %[[CALL]])<br>
+; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[CALL]])<br>
+<br>
+define i8* @test32() {<br>
+  %call = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)<br>
+  %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)<br>
+  ret i8* %1<br>
+}<br>
+<br>
 !0 = !{}<br>
<br>
 ; CHECK: attributes [[NUW]] = { nounwind }<br>
<br>
diff  --git a/llvm/test/Transforms/SCCP/clang-arc-rv.ll b/llvm/test/Transforms/SCCP/clang-arc-rv.ll<br>
new file mode 100644<br>
index 0000000000000..bb8f45b41c136<br>
--- /dev/null<br>
+++ b/llvm/test/Transforms/SCCP/clang-arc-rv.ll<br>
@@ -0,0 +1,24 @@<br>
+; RUN: opt < %s -ipsccp -S | FileCheck %s<br>
+; Return value can't be zapped if there is a call that has operand bundle<br>
+; "clang.arc.attachedcall".<br>
+<br>
+@g0 = global i8 zeroinitializer, align 1<br>
+<br>
+; CHECK-LABEL: @foo(<br>
+; CHECK: ret i8* @g0<br>
+<br>
+define internal i8* @foo() {<br>
+  ret i8* @g0<br>
+}<br>
+<br>
+; CHECK-LABEL: @test(<br>
+; CHECK: %[[R:.*]] = call i8* @foo()<br>
+; CHECK call void (...) @llvm.objc.clang.arc.noop.use(i8* %[[R]])<br>
+<br>
+define void @test() {<br>
+  %r = call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]<br>
+  call void (...) @llvm.objc.clang.arc.noop.use(i8* %r)<br>
+  ret void<br>
+}<br>
+<br>
+declare void @llvm.objc.clang.arc.noop.use(...)<br>
<br>
diff  --git a/llvm/test/Transforms/TailCallElim/deopt-bundle.ll b/llvm/test/Transforms/TailCallElim/deopt-bundle.ll<br>
index f651e462c1f56..a075849421716 100644<br>
--- a/llvm/test/Transforms/TailCallElim/deopt-bundle.ll<br>
+++ b/llvm/test/Transforms/TailCallElim/deopt-bundle.ll<br>
@@ -55,3 +55,13 @@ catch:<br>
 exit:<br>
   ret void<br>
 }<br>
+<br>
+; CHECK-LABEL: @test_clang_arc_attachedcall(<br>
+; CHECK: tail call i8* @getObj(<br>
+<br>
+declare i8* @getObj()<br>
+<br>
+define i8* @test_clang_arc_attachedcall() {<br>
+  %r = call i8* @getObj() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret i8* %r<br>
+}<br>
<br>
diff  --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll<br>
index 2598a7889f3fd..4ef0e647988af 100644<br>
--- a/llvm/test/Verifier/operand-bundles.ll<br>
+++ b/llvm/test/Verifier/operand-bundles.ll<br>
@@ -1,10 +1,13 @@<br>
 ; RUN: not opt -verify < %s 2>&1 | FileCheck %s<br>
<br>
+%0 = type opaque<br>
+declare void @g()<br>
+declare %0* @foo0()<br>
+declare i8 @foo1()<br>
+<br>
 ; Operand bundles uses are like regular uses, and need to be dominated<br>
 ; by their defs.<br>
<br>
-declare void @g()<br>
-<br>
 define void @f0(i32* %ptr) {<br>
 ; CHECK: Instruction does not dominate all uses!<br>
 ; CHECK-NEXT:  %x = add i32 42, 1<br>
@@ -60,3 +63,15 @@ define void @f_gc_transition(i32* %ptr) {<br>
   %x = add i32 42, 1<br>
   ret void<br>
 }<br>
+<br>
+define void @f_clang_arc_attachedcall() {<br>
+; CHECK: Multiple "clang.arc.attachedcall" operand bundles<br>
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i64 0), "clang.arc.attachedcall"(i64 0) ]<br>
+; CHECK-NEXT: must call a function returning a pointer<br>
+; CHECK-NEXT: call i8 @foo1() [ "clang.arc.attachedcall"(i64 0) ]<br>
+<br>
+  call %0* @foo0() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  call %0* @foo0() [ "clang.arc.attachedcall"(i64 0), "clang.arc.attachedcall"(i64 0) ]<br>
+  call i8 @foo1() [ "clang.arc.attachedcall"(i64 0) ]<br>
+  ret void<br>
+}<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div></div>