[ObjC][ARC] Replace uses of ObjC intrinsics that are arguments of

operand bundle "clang.arc.attachedcall" with ObjC runtime functions

The existing code only handles the case where the intrinsic being
rewritten is used as the called function pointer of a call/invoke.
This commit is contained in:
Akira Hatanaka 2021-11-08 21:19:07 -08:00
parent 0f2a7f2955
commit 1fe8993ad8
2 changed files with 49 additions and 1 deletions

View File

@ -13,6 +13,7 @@
#include "llvm/CodeGen/PreISelIntrinsicLowering.h" #include "llvm/CodeGen/PreISelIntrinsicLowering.h"
#include "llvm/Analysis/ObjCARCInstKind.h" #include "llvm/Analysis/ObjCARCInstKind.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/Passes.h"
#include "llvm/IR/Function.h" #include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h" #include "llvm/IR/IRBuilder.h"
@ -90,7 +91,20 @@ static bool lowerObjCCall(Function &F, const char *NewFn,
CallInst::TailCallKind OverridingTCK = getOverridingTailCallKind(F); CallInst::TailCallKind OverridingTCK = getOverridingTailCallKind(F);
for (auto I = F.use_begin(), E = F.use_end(); I != E;) { for (auto I = F.use_begin(), E = F.use_end(); I != E;) {
auto *CI = cast<CallInst>(I->getUser()); auto *CB = cast<CallBase>(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<CallInst>(CB);
assert(CI->getCalledFunction() && "Cannot lower an indirect call!"); assert(CI->getCalledFunction() && "Cannot lower an indirect call!");
++I; ++I;

View File

@ -3,6 +3,9 @@
; Make sure calls to the objc intrinsics are translated to calls in to the ; Make sure calls to the objc intrinsics are translated to calls in to the
; runtime ; runtime
declare i8* @foo()
declare i32 @__gxx_personality_v0(...)
define i8* @test_objc_autorelease(i8* %arg0) { define i8* @test_objc_autorelease(i8* %arg0) {
; CHECK-LABEL: test_objc_autorelease ; CHECK-LABEL: test_objc_autorelease
; CHECK-NEXT: entry ; CHECK-NEXT: entry
@ -153,6 +156,30 @@ entry:
ret i8* %0 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) { define i8* @test_objc_retainBlock(i8* %arg0) {
; CHECK-LABEL: test_objc_retainBlock ; CHECK-LABEL: test_objc_retainBlock
; CHECK-NEXT: entry ; CHECK-NEXT: entry
@ -193,6 +220,13 @@ entry:
ret i8* %0 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) { define i8* @test_objc_retainedObject(i8* %arg0) {
; CHECK-LABEL: test_objc_retainedObject ; CHECK-LABEL: test_objc_retainedObject
; CHECK-NEXT: entry ; CHECK-NEXT: entry