diff --git a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp index 9547fe6f93de..d9c726743db1 100644 --- a/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp +++ b/llvm/lib/CodeGen/PreISelIntrinsicLowering.cpp @@ -13,6 +13,7 @@ #include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/Analysis/ObjCARCInstKind.h" +#include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/CodeGen/Passes.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -90,7 +91,20 @@ static bool lowerObjCCall(Function &F, const char *NewFn, CallInst::TailCallKind OverridingTCK = getOverridingTailCallKind(F); for (auto I = F.use_begin(), E = F.use_end(); I != E;) { - auto *CI = cast(I->getUser()); + auto *CB = cast(I->getUser()); + + if (CB->getCalledFunction() != &F) { + objcarc::ARCInstKind Kind = objcarc::getAttachedARCFunctionKind(CB); + (void)Kind; + assert((Kind == objcarc::ARCInstKind::RetainRV || + Kind == objcarc::ARCInstKind::ClaimRV) && + "use expected to be the argument of operand bundle " + "\"clang.arc.attachedcall\""); + I++->set(FCache.getCallee()); + continue; + } + + auto *CI = cast(CB); assert(CI->getCalledFunction() && "Cannot lower an indirect call!"); ++I; diff --git a/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll b/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll index aff01910cd9b..67d8ff697e60 100644 --- a/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll +++ b/llvm/test/Transforms/PreISelIntrinsicLowering/objc-arc.ll @@ -3,6 +3,9 @@ ; Make sure calls to the objc intrinsics are translated to calls in to the ; runtime +declare i8* @foo() +declare i32 @__gxx_personality_v0(...) + define i8* @test_objc_autorelease(i8* %arg0) { ; CHECK-LABEL: test_objc_autorelease ; CHECK-NEXT: entry @@ -153,6 +156,30 @@ entry: ret i8* %0 } +define void @test_objc_retainAutoreleasedReturnValue_bundle() { +; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue_bundle( +; CHECK-NEXT: call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] + call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] + ret void +} + +define void @test_objc_retainAutoreleasedReturnValue_bundle_invoke() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-LABEL: test_objc_retainAutoreleasedReturnValue_bundle_invoke( +; CHECK-NEXT: entry +; CHECK-NEXT: invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_retainAutoreleasedReturnValue) ] +entry: + invoke i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ] + to label %invoke.cont unwind label %lpad + +invoke.cont: + ret void + +lpad: + %1 = landingpad { i8*, i32 } + cleanup + resume { i8*, i32 } %1 +} + define i8* @test_objc_retainBlock(i8* %arg0) { ; CHECK-LABEL: test_objc_retainBlock ; CHECK-NEXT: entry @@ -193,6 +220,13 @@ entry: ret i8* %0 } +define void @test_objc_unsafeClaimAutoreleasedReturnValue_bundle() { +; CHECK-LABEL: test_objc_unsafeClaimAutoreleasedReturnValue_bundle( +; CHECK-NEXT: call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @objc_unsafeClaimAutoreleasedReturnValue) ] + call i8* @foo() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ] + ret void +} + define i8* @test_objc_retainedObject(i8* %arg0) { ; CHECK-LABEL: test_objc_retainedObject ; CHECK-NEXT: entry