[llvm] dea6f71 - [ObjC][ARC] Use the addresses of the ARC runtime functions instead of

Akira Hatanaka via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 8 12:01:54 PDT 2021


Author: Akira Hatanaka
Date: 2021-09-08T11:58:03-07:00
New Revision: dea6f71af0fdd7c54cacd43f5fb15e293924fa20

URL: https://github.com/llvm/llvm-project/commit/dea6f71af0fdd7c54cacd43f5fb15e293924fa20
DIFF: https://github.com/llvm/llvm-project/commit/dea6f71af0fdd7c54cacd43f5fb15e293924fa20.diff

LOG: [ObjC][ARC] Use the addresses of the ARC runtime functions instead of
integer 0/1 for the operand of bundle "clang.arc.attachedcall"

https://reviews.llvm.org/D102996 changes the operand of bundle
"clang.arc.attachedcall". This patch makes changes to llvm that are
needed to handle the new IR.

This should make it easier to understand what the IR is doing and also
simplify some of the passes as they no longer have to translate the
integer values to the runtime functions.

Differential Revision: https://reviews.llvm.org/D103000

Added: 
    

Modified: 
    llvm/docs/LangRef.rst
    llvm/include/llvm/Analysis/ObjCARCUtil.h
    llvm/include/llvm/IR/Function.h
    llvm/include/llvm/IR/InstrTypes.h
    llvm/lib/IR/Function.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/lib/Target/X86/X86ExpandPseudo.cpp
    llvm/lib/Target/X86/X86ISelLowering.cpp
    llvm/lib/Target/X86/X86InstrCompiler.td
    llvm/lib/Target/X86/X86InstrControl.td
    llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
    llvm/lib/Transforms/ObjCARC/ObjCARC.h
    llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
    llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
    llvm/lib/Transforms/Utils/InlineFunction.cpp
    llvm/test/CodeGen/AArch64/call-rv-marker.ll
    llvm/test/CodeGen/X86/call-rv-marker.ll
    llvm/test/CodeGen/X86/expand-call-rvmarker.mir
    llvm/test/Transforms/DeadArgElim/deadretval.ll
    llvm/test/Transforms/Inline/inline-retainRV-call.ll
    llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
    llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
    llvm/test/Transforms/ObjCARC/rv.ll
    llvm/test/Transforms/SCCP/clang-arc-rv.ll
    llvm/test/Transforms/TailCallElim/deopt-bundle.ll
    llvm/test/Verifier/invoke.ll
    llvm/test/Verifier/operand-bundles.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 9ac310352e28b..3f2821f0d207b 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -2470,14 +2470,26 @@ for further details.
 ObjC ARC Attached Call Operand Bundles
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-A ``"clang.arc.attachedcall`` operand bundle on a call indicates the call is
+A ``"clang.arc.attachedcall"`` operand bundle on a call indicates the call is
 implicitly followed by a marker instruction and a call to an ObjC runtime
-function that uses the result of the call. If the argument passed to the operand
-bundle is 0, ``@objc_retainAutoreleasedReturnValue`` is called. If 1 is passed,
-``@objc_unsafeClaimAutoreleasedReturnValue`` is called. The return value of a
-call with this bundle is used by a call to ``@llvm.objc.clang.arc.noop.use``
-unless the called function's return type is void, in which case the operand
-bundle is ignored.
+function that uses the result of the call. The operand bundle takes either the
+pointer to the runtime function (``@objc_retainAutoreleasedReturnValue`` or
+``@objc_unsafeClaimAutoreleasedReturnValue``) or no arguments. If the bundle
+doesn't take any arguments, only the marker instruction has to be emitted after
+the call; the runtime function calls don't have to be emitted since they already
+have been emitted. The return value of a call with this bundle is used by a call
+to ``@llvm.objc.clang.arc.noop.use`` unless the called function's return type is
+void, in which case the operand bundle is ignored.
+
+.. code-block:: llvm
+
+   ; The marker instruction and a runtime function call are inserted after the call
+   ; to @foo.
+   call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
+   call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
+
+   ; Only the marker instruction is inserted after the call to @foo.
+   call i8* @foo() [ "clang.arc.attachedcall"() ]
 
 The operand bundle is needed to ensure the call is immediately followed by the
 marker instruction or the ObjC runtime call in the final output.

diff  --git a/llvm/include/llvm/Analysis/ObjCARCUtil.h b/llvm/include/llvm/Analysis/ObjCARCUtil.h
index 5e13a9424c112..362dd6c299925 100644
--- a/llvm/include/llvm/Analysis/ObjCARCUtil.h
+++ b/llvm/include/llvm/Analysis/ObjCARCUtil.h
@@ -14,6 +14,8 @@
 #ifndef LLVM_ANALYSIS_OBJCARCUTIL_H
 #define LLVM_ANALYSIS_OBJCARCUTIL_H
 
+#include "llvm/Analysis/ObjCARCInstKind.h"
+#include "llvm/IR/Function.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/LLVMContext.h"
 
@@ -24,13 +26,6 @@ inline const char *getRVMarkerModuleFlagStr() {
   return "clang.arc.retainAutoreleasedReturnValueMarker";
 }
 
-enum AttachedCallOperandBundle : unsigned { RVOB_Retain, RVOB_Claim };
-
-inline AttachedCallOperandBundle
-getAttachedCallOperandBundleEnum(bool IsRetain) {
-  return IsRetain ? RVOB_Retain : RVOB_Claim;
-}
-
 inline bool hasAttachedCallOpBundle(const CallBase *CB) {
   // Ignore the bundle if the return type is void. Global optimization passes
   // can turn the called function's return type to void. That should happen only
@@ -43,14 +38,32 @@ inline bool hasAttachedCallOpBundle(const CallBase *CB) {
              .hasValue();
 }
 
-inline bool hasAttachedCallOpBundle(const CallBase *CB, bool IsRetain) {
-  assert(hasAttachedCallOpBundle(CB) &&
-         "call doesn't have operand bundle clang_arc_attachedcall");
+/// This function returns operand bundle clang_arc_attachedcall's argument,
+/// which is the address of the ARC runtime function.
+inline Optional<Function *> getAttachedARCFunction(const CallBase *CB) {
   auto B = CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall);
-  if (!B.hasValue())
-    return false;
-  return cast<ConstantInt>(B->Inputs[0])->getZExtValue() ==
-         getAttachedCallOperandBundleEnum(IsRetain);
+  if (!B.hasValue() || B->Inputs.size() == 0)
+    return None;
+
+  return cast<Function>(B->Inputs[0]);
+}
+
+/// Check whether the function is retainRV/claimRV.
+inline bool isRetainOrClaimRV(ARCInstKind Kind) {
+  return Kind == ARCInstKind::RetainRV || Kind == ARCInstKind::ClaimRV;
+}
+
+/// This function returns the ARCInstKind of the function attached to operand
+/// bundle clang_arc_attachedcall. It returns None if the call doesn't have the
+/// operand bundle or the operand is null. Otherwise it returns either RetainRV
+/// or ClaimRV.
+inline ARCInstKind getAttachedARCFunctionKind(const CallBase *CB) {
+  Optional<Function *> Fn = getAttachedARCFunction(CB);
+  if (!Fn.hasValue())
+    return ARCInstKind::None;
+  auto FnClass = GetFunctionClass(*Fn);
+  assert(isRetainOrClaimRV(FnClass) && "unexpected ARC runtime function");
+  return FnClass;
 }
 
 } // end namespace objcarc

diff  --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h
index 97dee357ea2fa..36a756eba7f02 100644
--- a/llvm/include/llvm/IR/Function.h
+++ b/llvm/include/llvm/IR/Function.h
@@ -854,13 +854,14 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject,
   /// hasAddressTaken - returns true if there are any uses of this function
   /// other than direct calls or invokes to it, or blockaddress expressions.
   /// Optionally passes back an offending user for diagnostic purposes,
-  /// ignores callback uses, assume like pointer annotation calls, and
-  /// references in llvm.used and llvm.compiler.used variables.
-  ///
+  /// ignores callback uses, assume like pointer annotation calls, references in
+  /// llvm.used and llvm.compiler.used variables, and operand bundle
+  /// "clang.arc.attachedcall".
   bool hasAddressTaken(const User ** = nullptr,
                        bool IgnoreCallbackUses = false,
                        bool IgnoreAssumeLikeCalls = true,
-                       bool IngoreLLVMUsed = false) const;
+                       bool IngoreLLVMUsed = false,
+                       bool IgnoreARCAttachedCall = false) const;
 
   /// isDefTriviallyDead - Return true if it is trivially safe to remove
   /// this function definition from the module (because it isn't externally

diff  --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index f5b0845d2632f..8da0738dcc358 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1922,6 +1922,13 @@ class CallBase : public Instruction {
            Idx < getBundleOperandsEndIndex();
   }
 
+  /// Return true if the operand at index \p Idx is a bundle operand that has
+  /// tag ID \p ID.
+  bool isOperandBundleOfType(uint32_t ID, unsigned Idx) const {
+    return isBundleOperand(Idx) &&
+           getOperandBundleForOperand(Idx).getTagID() == ID;
+  }
+
   /// Returns true if the use is a bundle operand.
   bool isBundleOperand(const Use *U) const {
     assert(this == U->getUser() &&

diff  --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp
index 977cd852a330e..9ec5a46a02040 100644
--- a/llvm/lib/IR/Function.cpp
+++ b/llvm/lib/IR/Function.cpp
@@ -1745,8 +1745,8 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
 /// and llvm.compiler.used variables.
 bool Function::hasAddressTaken(const User **PutOffender,
                                bool IgnoreCallbackUses,
-                               bool IgnoreAssumeLikeCalls,
-                               bool IgnoreLLVMUsed) const {
+                               bool IgnoreAssumeLikeCalls, bool IgnoreLLVMUsed,
+                               bool IgnoreARCAttachedCall) const {
   for (const Use &U : uses()) {
     const User *FU = U.getUser();
     if (isa<BlockAddress>(FU))
@@ -1790,6 +1790,11 @@ bool Function::hasAddressTaken(const User **PutOffender,
       return true;
     }
     if (!Call->isCallee(&U)) {
+      if (IgnoreARCAttachedCall &&
+          Call->isOperandBundleOfType(LLVMContext::OB_clang_arc_attachedcall,
+                                      U.getOperandNo()))
+        continue;
+
       if (PutOffender)
         *PutOffender = FU;
       return true;

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index afdf2258138ef..354f09c028d77 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -569,6 +569,9 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
   /// declarations share the same calling convention.
   void verifyDeoptimizeCallingConvs();
 
+  void verifyAttachedCallBundle(const CallBase &Call,
+                                const OperandBundleUse &BU);
+
   /// Verify all-or-nothing property of DIFile source attribute within a CU.
   void verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F);
 
@@ -2521,7 +2524,8 @@ void Verifier::visitFunction(const Function &F) {
   // uses.
   if (F.isIntrinsic() && F.getParent()->isMaterialized()) {
     const User *U;
-    if (F.hasAddressTaken(&U))
+    if (F.hasAddressTaken(&U, false, true, false,
+                          /*IgnoreARCAttachedCall=*/true))
       Assert(false, "Invalid user of intrinsic instruction!", U);
   }
 
@@ -3264,17 +3268,10 @@ void Verifier::visitCallBase(CallBase &Call) {
       Assert(!FoundAttachedCallBundle,
              "Multiple \"clang.arc.attachedcall\" operand bundles", Call);
       FoundAttachedCallBundle = true;
+      verifyAttachedCallBundle(Call, BU);
     }
   }
 
-  if (FoundAttachedCallBundle)
-    Assert((FTy->getReturnType()->isPointerTy() ||
-            (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())),
-           "a call with operand bundle \"clang.arc.attachedcall\" must call a "
-           "function returning a pointer or a non-returning function that has "
-           "a void return type",
-           Call);
-
   // Verify that each inlinable callsite of a debug-info-bearing function in a
   // debug-info-bearing function has a debug location attached to it. Failure to
   // do so causes assertion failures when the inliner sets up inline scope info.
@@ -4402,10 +4399,21 @@ void Verifier::visitInstruction(Instruction &I) {
     }
 
     if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
+      // This code checks whether the function is used as the operand of a
+      // clang_arc_attachedcall operand bundle.
+      auto IsAttachedCallOperand = [](Function *F, const CallBase *CBI,
+                                      int Idx) {
+        return CBI && CBI->isOperandBundleOfType(
+                          LLVMContext::OB_clang_arc_attachedcall, Idx);
+      };
+
       // Check to make sure that the "address of" an intrinsic function is never
-      // taken.
-      Assert(!F->isIntrinsic() ||
-                 (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)),
+      // taken. Ignore cases where the address of the intrinsic function is used
+      // as the argument of operand bundle "clang.arc.attachedcall" as those
+      // cases are handled in verifyAttachedCallBundle.
+      Assert((!F->isIntrinsic() ||
+              (CBI && &CBI->getCalledOperandUse() == &I.getOperandUse(i)) ||
+              IsAttachedCallOperand(F, CBI, i)),
              "Cannot take the address of an intrinsic!", &I);
       Assert(
           !F->isIntrinsic() || isa<CallInst>(I) ||
@@ -4419,9 +4427,10 @@ void Verifier::visitInstruction(Instruction &I) {
               F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
               F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64 ||
               F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint ||
-              F->getIntrinsicID() == Intrinsic::wasm_rethrow,
+              F->getIntrinsicID() == Intrinsic::wasm_rethrow ||
+              IsAttachedCallOperand(F, CBI, i),
           "Cannot invoke an intrinsic other than donothing, patchpoint, "
-          "statepoint, coro_resume or coro_destroy",
+          "statepoint, coro_resume, coro_destroy or clang.arc.attachedcall",
           &I);
       Assert(F->getParent() == &M, "Referencing function in another module!",
              &I, &M, F, F->getParent());
@@ -5647,6 +5656,41 @@ void Verifier::verifyDeoptimizeCallingConvs() {
   }
 }
 
+void Verifier::verifyAttachedCallBundle(const CallBase &Call,
+                                        const OperandBundleUse &BU) {
+  FunctionType *FTy = Call.getFunctionType();
+
+  Assert((FTy->getReturnType()->isPointerTy() ||
+          (Call.doesNotReturn() && FTy->getReturnType()->isVoidTy())),
+         "a call with operand bundle \"clang.arc.attachedcall\" must call a "
+         "function returning a pointer or a non-returning function that has a "
+         "void return type",
+         Call);
+
+  Assert((BU.Inputs.empty() ||
+          (BU.Inputs.size() == 1 && isa<Function>(BU.Inputs.front()))),
+         "operand bundle \"clang.arc.attachedcall\" can take either no "
+         "arguments or one function as an argument",
+         Call);
+
+  if (BU.Inputs.empty())
+    return;
+
+  auto *Fn = cast<Function>(BU.Inputs.front());
+  Intrinsic::ID IID = Fn->getIntrinsicID();
+
+  if (IID) {
+    Assert((IID == Intrinsic::objc_retainAutoreleasedReturnValue ||
+            IID == Intrinsic::objc_unsafeClaimAutoreleasedReturnValue),
+           "invalid function argument", Call);
+  } else {
+    StringRef FnName = Fn->getName();
+    Assert((FnName == "objc_retainAutoreleasedReturnValue" ||
+            FnName == "objc_unsafeClaimAutoreleasedReturnValue"),
+           "invalid function argument", Call);
+  }
+}
+
 void Verifier::verifySourceDebugInfo(const DICompileUnit &U, const DIFile &F) {
   bool HasSource = F.getSource().hasValue();
   if (!HasSourceDebugInfo.count(&U))

diff  --git a/llvm/lib/Target/X86/X86ExpandPseudo.cpp b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
index 4add8d30e010e..ca7dfcdbb9cae 100644
--- a/llvm/lib/Target/X86/X86ExpandPseudo.cpp
+++ b/llvm/lib/Target/X86/X86ExpandPseudo.cpp
@@ -236,19 +236,10 @@ void X86ExpandPseudo::expandCALL_RVMARKER(MachineBasicBlock &MBB,
     MBB.getParent()->moveCallSiteInfo(&MI, Marker);
 
   // Emit call to ObjC runtime.
-  unsigned RuntimeCallType = MI.getOperand(0).getImm();
-  assert(RuntimeCallType <= 1 && "objc runtime call type must be 0 or 1");
-  Module *M = MBB.getParent()->getFunction().getParent();
-  auto &Context = M->getContext();
-  auto *I8PtrTy = PointerType::get(IntegerType::get(Context, 8), 0);
-  FunctionCallee Fn = M->getOrInsertFunction(
-      RuntimeCallType == 0 ? "objc_retainAutoreleasedReturnValue"
-                           : "objc_unsafeClaimAutoreleasedReturnValue",
-      FunctionType::get(I8PtrTy, {I8PtrTy}, false));
   const uint32_t *RegMask =
       TRI->getCallPreservedMask(*MBB.getParent(), CallingConv::C);
   BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(X86::CALL64pcrel32))
-      .addGlobalAddress(cast<GlobalValue>(Fn.getCallee()), 0, 0)
+      .addGlobalAddress(MI.getOperand(0).getGlobal(), 0, 0)
       .addRegMask(RegMask)
       .addReg(X86::RAX,
               RegState::Implicit |

diff  --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 9ba369e8c3321..75a3d190d3c49 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -4628,14 +4628,12 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
            "tail calls cannot be marked with clang.arc.attachedcall");
     assert(Is64Bit && "clang.arc.attachedcall is only supported in 64bit mode");
 
-    // Add target constant to select ObjC runtime call just before the call
-    // target. RuntimeCallType == 0 selects objc_retainAutoreleasedReturnValue,
-    // RuntimeCallType == 0 selects objc_unsafeClaimAutoreleasedReturnValue when
-    // epxanding the pseudo.
-    unsigned RuntimeCallType =
-        objcarc::hasAttachedCallOpBundle(CLI.CB, true) ? 0 : 1;
-    Ops.insert(Ops.begin() + 1,
-               DAG.getTargetConstant(RuntimeCallType, dl, MVT::i32));
+    // Add a target global address for the retainRV/claimRV runtime function
+    // just before the call target.
+    Function *ARCFn = *objcarc::getAttachedARCFunction(CLI.CB);
+    auto PtrVT = getPointerTy(DAG.getDataLayout());
+    auto GA = DAG.getTargetGlobalAddress(ARCFn, dl, PtrVT);
+    Ops.insert(Ops.begin() + 1, GA);
     Chain = DAG.getNode(X86ISD::CALL_RVMARKER, dl, NodeTys, Ops);
   } else {
     Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops);

diff  --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td
index b35e23ac80477..afafe976eff56 100644
--- a/llvm/lib/Target/X86/X86InstrCompiler.td
+++ b/llvm/lib/Target/X86/X86InstrCompiler.td
@@ -1215,10 +1215,10 @@ def : Pat<(X86call (i64 tglobaladdr:$dst)),
 def : Pat<(X86call (i64 texternalsym:$dst)),
           (CALL64pcrel32 texternalsym:$dst)>;
 
-def : Pat<(X86call_rvmarker (timm:$sel), (i64 texternalsym:$dst)),
-          (CALL64pcrel32_RVMARKER timm:$sel, texternalsym:$dst)>;
-def : Pat<(X86call_rvmarker (timm:$sel), (i64 tglobaladdr:$dst)),
-          (CALL64pcrel32_RVMARKER timm:$sel, tglobaladdr:$dst)>;
+def : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 texternalsym:$dst)),
+          (CALL64pcrel32_RVMARKER tglobaladdr:$rvfunc, texternalsym:$dst)>;
+def : Pat<(X86call_rvmarker (i64 tglobaladdr:$rvfunc), (i64 tglobaladdr:$dst)),
+          (CALL64pcrel32_RVMARKER tglobaladdr:$rvfunc, tglobaladdr:$dst)>;
 
 
 // Tailcall stuff. The TCRETURN instructions execute after the epilog, so they

diff  --git a/llvm/lib/Target/X86/X86InstrControl.td b/llvm/lib/Target/X86/X86InstrControl.td
index a6cb17f17a179..680389662aa87 100644
--- a/llvm/lib/Target/X86/X86InstrControl.td
+++ b/llvm/lib/Target/X86/X86InstrControl.td
@@ -419,15 +419,15 @@ let isPseudo = 1, isCall = 1, isCodeGenOnly = 1,
     Uses = [RSP, SSP],
     SchedRW = [WriteJump] in {
   def CALL64m_RVMARKER :
-     PseudoI<(outs), (ins i32imm:$sel, i64mem:$dst), [(X86call_rvmarker timm:$sel, (loadi64 addr:$dst))]>,
+     PseudoI<(outs), (ins i64imm:$rvfunc, i64mem:$dst), [(X86call_rvmarker tglobaladdr:$rvfunc, (loadi64 addr:$dst))]>,
              Requires<[In64BitMode]>;
 
   def CALL64r_RVMARKER :
-    PseudoI<(outs), (ins i32imm:$sel, GR64:$dst), [(X86call_rvmarker timm:$sel, GR64:$dst)]>,
+    PseudoI<(outs), (ins i64imm:$rvfunc, GR64:$dst), [(X86call_rvmarker tglobaladdr:$rvfunc, GR64:$dst)]>,
             Requires<[In64BitMode]>;
 
   def CALL64pcrel32_RVMARKER :
-    PseudoI<(outs), (ins i32imm:$sel, i64i32imm_brtarget:$dst), []>,
+    PseudoI<(outs), (ins i64imm:$rvfunc, i64i32imm_brtarget:$dst), []>,
             Requires<[In64BitMode]>;
 }
 

diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
index 06b12149f5971..296610eedccd9 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp
@@ -103,9 +103,8 @@ CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
     Instruction *InsertPt, CallBase *AnnotatedCall,
     const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
   IRBuilder<> Builder(InsertPt);
-  bool IsRetainRV = objcarc::hasAttachedCallOpBundle(AnnotatedCall, true);
-  Function *Func = EP.get(IsRetainRV ? ARCRuntimeEntryPointKind::RetainRV
-                                     : ARCRuntimeEntryPointKind::ClaimRV);
+  Function *Func = *objcarc::getAttachedARCFunction(AnnotatedCall);
+  assert(Func && "operand isn't a Function");
   Type *ParamTy = Func->getArg(0)->getType();
   Value *CallArg = Builder.CreateBitCast(AnnotatedCall, ParamTy);
   auto *Call =
@@ -116,13 +115,21 @@ CallInst *BundledRetainClaimRVs::insertRVCallWithColors(
 
 BundledRetainClaimRVs::~BundledRetainClaimRVs() {
   if (ContractPass) {
-    // At this point, we know that the annotated calls can't be tail calls as
-    // they are followed by marker instructions and retainRV/claimRV calls. Mark
-    // them as notail, so that the backend knows these calls can't be tail
-    // calls.
-    for (auto P : RVCalls)
-      if (auto *CI = dyn_cast<CallInst>(P.second))
+    for (auto P : RVCalls) {
+      CallBase *CB = P.second;
+      // At this point, we know that the annotated calls can't be tail calls
+      // as they are followed by marker instructions and retainRV/claimRV
+      // calls. Mark them as notail so that the backend knows these calls
+      // can't be tail calls.
+      if (auto *CI = dyn_cast<CallInst>(CB))
         CI->setTailCallKind(CallInst::TCK_NoTail);
+
+      // Remove the ARC intrinsic function operand from the operand bundle.
+      OperandBundleDef OB("clang.arc.attachedcall", None);
+      auto *NewCB = CallBase::Create(CB, OB, CB);
+      CB->replaceAllUsesWith(NewCB);
+      CB->eraseFromParent();
+    }
   } else {
     for (auto P : RVCalls)
       EraseInstruction(P.first);

diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
index 1f9d76969bfd7..62f88a8cc02ba 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h
@@ -105,8 +105,7 @@ CallInst *createCallInstWithColors(
 
 class BundledRetainClaimRVs {
 public:
-  BundledRetainClaimRVs(ARCRuntimeEntryPoints &P, bool ContractPass)
-      : EP(P), ContractPass(ContractPass) {}
+  BundledRetainClaimRVs(bool ContractPass) : ContractPass(ContractPass) {}
   ~BundledRetainClaimRVs();
 
   /// Insert a retainRV/claimRV call to the normal destination blocks of invokes
@@ -155,7 +154,6 @@ class BundledRetainClaimRVs {
   /// A map of inserted retainRV/claimRV calls to annotated calls/invokes.
   DenseMap<CallInst *, CallBase *> RVCalls;
 
-  ARCRuntimeEntryPoints &EP;
   bool ContractPass;
 };
 

diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
index 577973c806015..185a19fc47f40 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp
@@ -540,7 +540,7 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) {
   AA = A;
   DT = D;
   PA.setAA(A);
-  BundledRetainClaimRVs BRV(EP, true);
+  BundledRetainClaimRVs BRV(true);
   BundledInsts = &BRV;
 
   std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT);

diff  --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
index ada6aa8d9b6dc..89e62267389f2 100644
--- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
+++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp
@@ -2462,7 +2462,7 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) {
     return false;
 
   Changed = CFGChanged = false;
-  BundledRetainClaimRVs BRV(EP, false);
+  BundledRetainClaimRVs BRV(false);
   BundledInsts = &BRV;
 
   LLVM_DEBUG(dbgs() << "<<< ObjCARCOpt: Visiting Function: " << F.getName()

diff  --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index e985fece6ab26..966f95d1458fd 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -1671,10 +1671,11 @@ void llvm::updateProfileCallee(
 /// 3. Otherwise, a call to objc_retain is inserted if the call in the caller is
 ///    a retainRV call.
 static void
-inlineRetainOrClaimRVCalls(CallBase &CB,
+inlineRetainOrClaimRVCalls(CallBase &CB, objcarc::ARCInstKind RVCallKind,
                            const SmallVectorImpl<ReturnInst *> &Returns) {
   Module *Mod = CB.getModule();
-  bool IsRetainRV = objcarc::hasAttachedCallOpBundle(&CB, true),
+  assert(objcarc::isRetainOrClaimRV(RVCallKind) && "unexpected ARC function");
+  bool IsRetainRV = RVCallKind == objcarc::ARCInstKind::RetainRV,
        IsClaimRV = !IsRetainRV;
 
   for (auto *RI : Returns) {
@@ -1727,9 +1728,7 @@ inlineRetainOrClaimRVCalls(CallBase &CB,
 
       // If we've found an unannotated call that defines RetOpnd, add a
       // "clang.arc.attachedcall" operand bundle.
-      Value *BundleArgs[] = {ConstantInt::get(
-          Builder.getInt64Ty(),
-          objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};
+      Value *BundleArgs[] = {*objcarc::getAttachedARCFunction(&CB)};
       OperandBundleDef OB("clang.arc.attachedcall", BundleArgs);
       auto *NewCall = CallBase::addOperandBundle(
           CI, LLVMContext::OB_clang_arc_attachedcall, OB, CI);
@@ -1965,8 +1964,9 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
     FirstNewBlock = LastBlock; ++FirstNewBlock;
 
     // Insert retainRV/clainRV runtime calls.
-    if (objcarc::hasAttachedCallOpBundle(&CB))
-      inlineRetainOrClaimRVCalls(CB, Returns);
+    objcarc::ARCInstKind RVCallKind = objcarc::getAttachedARCFunctionKind(&CB);
+    if (RVCallKind != objcarc::ARCInstKind::None)
+      inlineRetainOrClaimRVCalls(CB, RVCallKind, Returns);
 
     // Updated caller/callee profiles only when requested. For sample loader
     // inlining, the context-sensitive inlinee profile doesn't need to be

diff  --git a/llvm/test/CodeGen/AArch64/call-rv-marker.ll b/llvm/test/CodeGen/AArch64/call-rv-marker.ll
index 3b5ab40839b57..3f53b5b487279 100644
--- a/llvm/test/CodeGen/AArch64/call-rv-marker.ll
+++ b/llvm/test/CodeGen/AArch64/call-rv-marker.ll
@@ -33,7 +33,7 @@ define dso_local i8* @rv_marker_1() {
 ; GISEL-NOT:       mov x29, x29
 ;
 entry:
-  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"() ]
   ret i8* %call
 }
 
@@ -49,7 +49,7 @@ define dso_local void @rv_marker_2_select(i32 %c) {
 entry:
   %tobool.not = icmp eq i32 %c, 0
   %.sink = select i1 %tobool.not, i32 2, i32 1
-  %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i64 0) ]
+  %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"() ]
   tail call void @foo2(i8* %call1)
   ret void
 }
@@ -61,7 +61,7 @@ define dso_local void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_
 ; SELDAG-NEXT:   mov x29, x29
 ;
 entry:
-  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"() ]
   invoke void @objc_object(i8* %call) #5
           to label %invoke.cont unwind label %lpad
 
@@ -87,7 +87,7 @@ entry:
   %s = alloca %struct.S, align 1
   %0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0
   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2
-  %call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = invoke i8* @foo1() [ "clang.arc.attachedcall"() ]
           to label %invoke.cont unwind label %lpad
 
 invoke.cont:                                      ; preds = %entry
@@ -127,7 +127,7 @@ define dso_local i8* @rv_marker_5_indirect_call() {
 ;
 entry:
   %0 = load i8* ()*, i8* ()** @fptr, align 8
-  %call = call i8* %0() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* %0() [ "clang.arc.attachedcall"() ]
   tail call void @foo2(i8* %call)
   ret i8* %call
 }
@@ -142,7 +142,7 @@ define dso_local void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {
 ; CHECK-NEXT:   bl  foo
 ; SELDAG-NEXT:  mov x29, x29
 ; GISEL-NOT:    mov x29, x29
-  call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i64 0) ]
+  call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"() ]
   ret void
 }
 

diff  --git a/llvm/test/CodeGen/X86/call-rv-marker.ll b/llvm/test/CodeGen/X86/call-rv-marker.ll
index 91a0e61f5e5af..fd22ec59e5f73 100644
--- a/llvm/test/CodeGen/X86/call-rv-marker.ll
+++ b/llvm/test/CodeGen/X86/call-rv-marker.ll
@@ -34,7 +34,7 @@ define i8* @rv_marker_1_retain() {
 ; CHECK-NEXT:    retq
 ;
 entry:
-  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   ret i8* %call
 }
 
@@ -49,7 +49,7 @@ define i8* @rv_marker_1_claim() {
 ; CHECK-NEXT:    retq
 ;
 entry:
-  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 1) ]
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
   ret i8* %call
 }
 
@@ -70,7 +70,7 @@ define void @rv_marker_2_select(i32 %c) {
 entry:
   %tobool.not = icmp eq i32 %c, 0
   %.sink = select i1 %tobool.not, i32 2, i32 1
-  %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i64 0) ]
+  %call1 = call i8* @foo0(i32 %.sink) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   tail call void @foo2(i8* %call1)
   ret void
 }
@@ -92,7 +92,7 @@ define void @rv_marker_3() personality i8* bitcast (i32 (...)* @__gxx_personalit
 ; CHECK-NEXT: Ltmp0:
 ;
 entry:
-  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   invoke void @objc_object(i8* %call) #5
           to label %invoke.cont unwind label %lpad
 
@@ -127,7 +127,7 @@ entry:
   %s = alloca %struct.S, align 1
   %0 = getelementptr inbounds %struct.S, %struct.S* %s, i64 0, i32 0
   call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0) #2
-  %call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = invoke i8* @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
           to label %invoke.cont unwind label %lpad
 
 invoke.cont:                                      ; preds = %entry
@@ -177,7 +177,7 @@ define i8* @rv_marker_5_indirect_call() {
 ;
 entry:
   %lv = load i8* ()*, i8* ()** @fptr, align 8
-  %call = call i8* %lv() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* %lv() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   tail call void @foo2(i8* %call)
   ret i8* %call
 }
@@ -197,7 +197,7 @@ define void @rv_marker_multiarg(i64 %a, i64 %b, i64 %c) {
 ; CHECK-NEXT:    popq    %rax
 ; CHECK-NEXT:    retq
 ;
-  %r = call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i64 0) ]
+  %r = call i8* @foo(i64 %c, i64 %b, i64 %a) [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   ret void
 }
 
@@ -210,10 +210,12 @@ define void @test_nonlazybind() {
 ; CHECK-NEXT:  movq    %rax, %rdi
 ; CHECK-NEXT:  callq   _objc_retainAutoreleasedReturnValue
 ;
-  %call1 = notail call i8* @foo_nonlazybind() [ "clang.arc.attachedcall"(i64 0) ]
+  %call1 = notail call i8* @foo_nonlazybind() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
   ret void
 }
 
 declare i8* @foo_nonlazybind()  nonlazybind
 
+declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
 declare i32 @__gxx_personality_v0(...)

diff  --git a/llvm/test/CodeGen/X86/expand-call-rvmarker.mir b/llvm/test/CodeGen/X86/expand-call-rvmarker.mir
index f4f8fabf1a877..e83090e22f7e4 100644
--- a/llvm/test/CodeGen/X86/expand-call-rvmarker.mir
+++ b/llvm/test/CodeGen/X86/expand-call-rvmarker.mir
@@ -52,7 +52,7 @@ body:             |
   bb.0 (%ir-block.0):
     frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
     CFI_INSTRUCTION def_cfa_offset 16
-    CALL64pcrel32_RVMARKER 0, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
+    CALL64pcrel32_RVMARKER @objc_retainAutoreleasedReturnValue, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
     $rcx = frame-destroy POP64r implicit-def $rsp, implicit $rsp
     RET 0, $rax
 
@@ -83,7 +83,7 @@ body:             |
   bb.0 (%ir-block.0):
     frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
     CFI_INSTRUCTION def_cfa_offset 16
-    CALL64pcrel32_RVMARKER 1, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
+    CALL64pcrel32_RVMARKER @objc_unsafeClaimAutoreleasedReturnValue, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def $rax
     $rcx = frame-destroy POP64r implicit-def $rsp, implicit $rsp
     RET 0, $rax
 
@@ -120,7 +120,7 @@ body:             |
     $rax = MOV64rr $rdi
     $rdi = MOV64rr killed $rdx
     $rdx = MOV64rr killed $rax
-    CALL64pcrel32_RVMARKER 0, @fn, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax
+    CALL64pcrel32_RVMARKER @objc_retainAutoreleasedReturnValue, @fn, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit $rsi, implicit $rdx, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax
     $rax = frame-destroy POP64r implicit-def $rsp, implicit $rsp
     RET 0, $rax
 
@@ -150,6 +150,6 @@ body:             |
   bb.0 (%ir-block.0):
     frame-setup PUSH64r undef $rax, implicit-def $rsp, implicit $rsp
     CFI_INSTRUCTION def_cfa_offset 16
-    CALL64pcrel32_RVMARKER 0, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax
+    CALL64pcrel32_RVMARKER @objc_retainAutoreleasedReturnValue, @fn, csr_64, implicit $rsp, implicit $ssp, implicit-def $rsp, implicit-def $ssp, implicit-def dead $rax
     $rax = frame-destroy POP64r implicit-def $rsp, implicit $rsp
     RET 0

diff  --git a/llvm/test/Transforms/DeadArgElim/deadretval.ll b/llvm/test/Transforms/DeadArgElim/deadretval.ll
index f3b343745e4d2..750e8f27bc3be 100644
--- a/llvm/test/Transforms/DeadArgElim/deadretval.ll
+++ b/llvm/test/Transforms/DeadArgElim/deadretval.ll
@@ -32,10 +32,12 @@ define internal i8* @callee4(i8* %a0) {
 declare void @llvm.objc.clang.arc.noop.use(...)
 
 ; CHECK-LABEL: define i8* @test4(
-; CHECK: tail call i8* @callee4() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: tail call i8* @callee4() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 
 define i8* @test4() {
-  %call = tail call i8* @callee4(i8* @g0) [ "clang.arc.attachedcall"(i64 0) ]
+  %call = tail call i8* @callee4(i8* @g0) [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)
   ret i8* @g0
 }
+
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)

diff  --git a/llvm/test/Transforms/Inline/inline-retainRV-call.ll b/llvm/test/Transforms/Inline/inline-retainRV-call.ll
index f8ac2154f9339..774663895f1ac 100644
--- a/llvm/test/Transforms/Inline/inline-retainRV-call.ll
+++ b/llvm/test/Transforms/Inline/inline-retainRV-call.ll
@@ -4,35 +4,35 @@
 declare i8* @foo0()
 
 define i8* @callee0_autoreleaseRV() {
-  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
   ret i8* %call
 }
 
 ; CHECK-LABEL: define void @test0_autoreleaseRV(
-; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 
 define void @test0_autoreleaseRV() {
-  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL: define void @test0_claimRV_autoreleaseRV(
-; CHECK: %[[CALL:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[CALL:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK: call void @llvm.objc.release(i8* %[[CALL]])
 ; CHECK-NEXT: ret void
 
 define void @test0_claimRV_autoreleaseRV() {
-  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
+  %call = call i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL: define void @test1_autoreleaseRV(
-; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 
 define void @test1_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
-  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
           to label %invoke.cont unwind label %lpad
 
 invoke.cont:
@@ -45,13 +45,13 @@ lpad:
 }
 
 ; CHECK-LABEL: define void @test1_claimRV_autoreleaseRV(
-; CHECK: %[[INVOKE:.*]] = invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[INVOKE:.*]] = invoke i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK: call void @llvm.objc.release(i8* %[[INVOKE]])
 ; CHECK-NEXT: br
 
 define void @test1_claimRV_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
-  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
+  %call = invoke i8* @callee0_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
           to label %invoke.cont unwind label %lpad
 
 invoke.cont:
@@ -69,29 +69,29 @@ define i8* @callee1_no_autoreleaseRV() {
 }
 
 ; CHECK-LABEL: define void @test2_no_autoreleaseRV(
-; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK-NEXT: ret void
 
 define void @test2_no_autoreleaseRV() {
-  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL: define void @test2_claimRV_no_autoreleaseRV(
-; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i64 1) ]
+; CHECK: call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
 ; CHECK-NEXT: ret void
 
 define void @test2_claimRV_no_autoreleaseRV() {
-  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 1) ]
+  %call = call i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL: define void @test3_no_autoreleaseRV(
-; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: invoke i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 
 define void @test3_no_autoreleaseRV() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
-  %call = invoke i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = invoke i8* @callee1_no_autoreleaseRV() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
           to label %invoke.cont unwind label %lpad
 
 invoke.cont:
@@ -117,7 +117,7 @@ define i8* @callee2_nocall() {
 ; CHECK-NEXT: ret void
 
 define void @test4_nocall() {
-  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
@@ -126,7 +126,7 @@ define void @test4_nocall() {
 ; CHECK-NEXT: ret void
 
 define void @test4_claimRV_nocall() {
-  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i64 1) ]
+  %call = call i8* @callee2_nocall() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   ret void
 }
 
@@ -134,17 +134,17 @@ define void @test4_claimRV_nocall() {
 ; the attribute. I'm not sure this will happen in practice.
 
 define i8* @callee3_marker() {
-  %1 = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+  %1 = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret i8* %1
 }
 
 ; CHECK-LABEL: define void @test5(
-; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK-NEXT: call i8* @llvm.objc.retain(i8* %[[V0]])
 ; CHECK-NEXT: ret void
 
 define void @test5() {
-  %call = call i8* @callee3_marker() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @callee3_marker() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
@@ -153,23 +153,25 @@ define void @test5() {
 ; autoreleaseRV that isn't a cast instruction.
 
 define i8* @callee0_autoreleaseRV2() {
-  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   %1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
   store i8* null, i8** @g0
   ret i8* %call
 }
 
 ; CHECK-LABEL: define void @test6(
-; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[V0:.*]] = call i8* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[V0]])
 ; CHECK: store i8* null, i8** @g0, align 8
 ; CHECK: call i8* @llvm.objc.retain(i8* %[[V0]])
 ; CHECK-NEXT: ret void
 
 define void @test6() {
-  %call = call i8* @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @callee0_autoreleaseRV2() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
 declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
 declare i32 @__gxx_personality_v0(...)

diff  --git a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
index c40f411c9fb75..fb3dbc0272f44 100644
--- a/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
+++ b/llvm/test/Transforms/ObjCARC/contract-marker-funclet.ll
@@ -51,11 +51,11 @@ invoke.cont:                                      ; preds = %entry
 }
 
 ; CHECK-LABEL: define dso_local void @"?test_attr_claimRV@@YAXXZ"()
-; CHECK: %[[CALL4:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "clang.arc.attachedcall"(i64 1) ]
+; CHECK: %[[CALL4:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "clang.arc.attachedcall"() ]
 ; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL4]])
 
 ; CHECK: %[[V1:.*]] = cleanuppad
-; CHECK: %[[CALL:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "funclet"(token %[[V1]]), "clang.arc.attachedcall"(i64 1) ]
+; CHECK: %[[CALL:.*]] = notail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() [ "funclet"(token %[[V1]]), "clang.arc.attachedcall"() ]
 ; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]]) [ "funclet"(token %[[V1]]) ]
 
 define dso_local void @"?test_attr_claimRV@@YAXXZ"() local_unnamed_addr #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
@@ -64,12 +64,12 @@ entry:
           to label %invoke.cont unwind label %ehcleanup
 
 invoke.cont:                                      ; preds = %entry
-  %call.i4 = tail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "clang.arc.attachedcall"(i64 1) ]
+  %call.i4 = tail call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   ret void
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  %call.i = call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "funclet"(token %0), "clang.arc.attachedcall"(i64 1) ]
+  %call.i = call i8* @"?noexcept_func@@YAPAUobjc_object@@XZ"() #2 [ "funclet"(token %0), "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   cleanupret from %0 unwind to caller
 }
 

diff  --git a/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
index 18bc00b62db8d..d601e988fdb32 100644
--- a/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
+++ b/llvm/test/Transforms/ObjCARC/contract-rv-attr.ll
@@ -2,30 +2,30 @@
 ; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s
 
 ; CHECK-LABEL: define void @test0() {
-; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
 ; CHECK: call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL]])
 
 define void @test0() {
-  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL: define void @test1() {
-; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]
+; CHECK: %[[CALL:.*]] = notail call i8* @foo() [ "clang.arc.attachedcall"() ]
 ; CHECK: call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* %[[CALL]])
 
 define void @test1() {
-  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]
+  %call1 = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   ret void
 }
 
 ; CHECK-LABEL:define i8* @test2(
-; CHECK: %[[CALL1:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[CALL1:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"() ]
 
 ; CHECK: %[[V0:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL1]])
 ; CHECK-NEXT: br
 
-; CHECK: %[[CALL3:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[CALL3:.*]] = invoke i8* @foo() [ "clang.arc.attachedcall"() ]
 
 ; CHECK: %[[V2:.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %[[CALL3]])
 ; CHECK-NEXT: br
@@ -38,7 +38,7 @@ entry:
   br i1 %b, label %if.then, label %if.end
 
 if.then:
-  %call1 = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+  %call1 = invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
           to label %cleanup unwind label %lpad
 
 lpad:
@@ -47,7 +47,7 @@ lpad:
   resume { i8*, i32 } undef
 
 if.end:
-  %call3 = invoke i8* @foo() [ "clang.arc.attachedcall"(i64 0) ]
+  %call3 = invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
           to label %cleanup unwind label %lpad
 
 cleanup:
@@ -55,18 +55,21 @@ cleanup:
   ret i8* %retval.0
 }
 
+; "clang.arc.attachedcall" is ignored if the return type of the called function is void.
 ; CHECK-LABEL: define void @test3(
-; CHECK: call void @foo2() #[[ATTR1:.*]] [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: call void @foo2() #[[ATTR1:.*]] [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK-NEXT: ret void
 
 define void @test3() {
-  call void @foo2() #0 [ "clang.arc.attachedcall"(i64 0) ]
+  call void @foo2() #0 [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret void
 }
 
 declare i8* @foo()
 declare void @foo2()
 declare i32 @__gxx_personality_v0(...)
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
 
 !llvm.module.flags = !{!0}
 

diff  --git a/llvm/test/Transforms/ObjCARC/rv.ll b/llvm/test/Transforms/ObjCARC/rv.ll
index 29017222ebb11..7fda98cf122ca 100644
--- a/llvm/test/Transforms/ObjCARC/rv.ll
+++ b/llvm/test/Transforms/ObjCARC/rv.ll
@@ -461,19 +461,19 @@ bb1:
 ; CHECK-NEXT: ret i8* %[[CALL]]
 
 define i8* @test31() {
-  %call = tail call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = tail call i8* @returner() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)
   %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
   ret i8* %1
 }
 
 ; CHECK-LABEL: define i8* @test32(
-; CHECK: %[[CALL:.*]] = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK: %[[CALL:.*]] = call i8* @returner() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK: call void (...) @llvm.objc.clang.arc.noop.use(i8* %[[CALL]])
 ; CHECK: call i8* @llvm.objc.autoreleaseReturnValue(i8* %[[CALL]])
 
 define i8* @test32() {
-  %call = call i8* @returner() [ "clang.arc.attachedcall"(i64 0) ]
+  %call = call i8* @returner() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   call void (...) @llvm.objc.clang.arc.noop.use(i8* %call)
   %1 = call i8* @llvm.objc.autoreleaseReturnValue(i8* %call)
   ret i8* %1

diff  --git a/llvm/test/Transforms/SCCP/clang-arc-rv.ll b/llvm/test/Transforms/SCCP/clang-arc-rv.ll
index bb8f45b41c136..7ac2eb0ae3bbd 100644
--- a/llvm/test/Transforms/SCCP/clang-arc-rv.ll
+++ b/llvm/test/Transforms/SCCP/clang-arc-rv.ll
@@ -16,9 +16,10 @@ define internal i8* @foo() {
 ; CHECK call void (...) @llvm.objc.clang.arc.noop.use(i8* %[[R]])
 
 define void @test() {
-  %r = call i8* @foo() [ "clang.arc.attachedcall"(i64 1) ]
+  %r = call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
   call void (...) @llvm.objc.clang.arc.noop.use(i8* %r)
   ret void
 }
 
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
 declare void @llvm.objc.clang.arc.noop.use(...)

diff  --git a/llvm/test/Transforms/TailCallElim/deopt-bundle.ll b/llvm/test/Transforms/TailCallElim/deopt-bundle.ll
index a075849421716..310ecc1a8ee17 100644
--- a/llvm/test/Transforms/TailCallElim/deopt-bundle.ll
+++ b/llvm/test/Transforms/TailCallElim/deopt-bundle.ll
@@ -62,6 +62,8 @@ exit:
 declare i8* @getObj()
 
 define i8* @test_clang_arc_attachedcall() {
-  %r = call i8* @getObj() [ "clang.arc.attachedcall"(i64 0) ]
+  %r = call i8* @getObj() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
   ret i8* %r
 }
+
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)

diff  --git a/llvm/test/Verifier/invoke.ll b/llvm/test/Verifier/invoke.ll
index 12c1a259520ff..efc7d4d11edf2 100644
--- a/llvm/test/Verifier/invoke.ll
+++ b/llvm/test/Verifier/invoke.ll
@@ -46,7 +46,7 @@ contb:
 
 define i8 @f2() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
 entry:
-; CHECK: Cannot invoke an intrinsic other than donothing, patchpoint, statepoint, coro_resume or coro_destroy
+; CHECK: Cannot invoke an intrinsic other than donothing, patchpoint, statepoint, coro_resume, coro_destroy or clang.arc.attachedcall
   invoke void @llvm.trap()
   to label %cont unwind label %lpad
 

diff  --git a/llvm/test/Verifier/operand-bundles.ll b/llvm/test/Verifier/operand-bundles.ll
index d7d7b4f0f7820..06b452de910c4 100644
--- a/llvm/test/Verifier/operand-bundles.ll
+++ b/llvm/test/Verifier/operand-bundles.ll
@@ -67,18 +67,40 @@ define void @f_gc_transition(i32* %ptr) {
 
 define void @f_clang_arc_attachedcall() {
 ; CHECK: Multiple "clang.arc.attachedcall" operand bundles
-; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i64 0), "clang.arc.attachedcall"(i64 0) ]
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue), "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK-NEXT: must call a function returning a pointer
-; CHECK-NEXT: call i8 @foo1() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK-NEXT: call i8 @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
 ; CHECK-NEXT: or a non-returning function
-; CHECK-NEXT: call void @g() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK-NEXT: call void @g() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+; CHECK-NEXT: can take either no arguments
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* null) ]
+; CHECK-NEXT: can take either no arguments
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
+; CHECK-NEXT: invalid function argument
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(i8 ()* @foo1) ]
+; CHECK-NEXT: invalid function argument
+; CHECK-NEXT: call %0* @foo0() [ "clang.arc.attachedcall"(void (i1)* @llvm.assume) ]
 
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"() ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue), "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+  call i8 @foo1() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+  call void @noreturn_func() #0 [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+  call void @g() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8* (i8*)* null) ]
   call %0* @foo0() [ "clang.arc.attachedcall"(i64 0) ]
-  call %0* @foo0() [ "clang.arc.attachedcall"(i64 0), "clang.arc.attachedcall"(i64 0) ]
-  call i8 @foo1() [ "clang.arc.attachedcall"(i64 0) ]
-  call void @noreturn_func() #0 [ "clang.arc.attachedcall"(i64 0) ]
-  call void @g() [ "clang.arc.attachedcall"(i64 0) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(i8 ()* @foo1) ]
+  call %0* @foo0() [ "clang.arc.attachedcall"(void (i1)* @llvm.assume) ]
   ret void
 }
 
+declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
+declare i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8*)
+declare i8* @objc_retainAutoreleasedReturnValue(i8*)
+declare i8* @objc_unsafeClaimAutoreleasedReturnValue(i8*)
+declare void @llvm.assume(i1)
+
 attributes #0 = { noreturn }


        


More information about the llvm-commits mailing list