Skip to content

Commit

Permalink
[ObjC][ARC] Use the addresses of the ARC runtime functions instead of
Browse files Browse the repository at this point in the history
integer 0/1 for the operand of bundle "clang.arc.attachedcall"

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/D102996
  • Loading branch information
ahatanaka committed Sep 8, 2021
1 parent ff77c4e commit 59cc39a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 57 deletions.
80 changes: 34 additions & 46 deletions clang/lib/CodeGen/CGObjC.cpp
Expand Up @@ -2108,6 +2108,13 @@ static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
setARCRuntimeFunctionLinkage(CGM, RTF.getCallee());
}

static llvm::Function *getARCIntrinsic(llvm::Intrinsic::ID IntID,
CodeGenModule &CGM) {
llvm::Function *fn = CGM.getIntrinsic(IntID);
setARCRuntimeFunctionLinkage(CGM, fn);
return fn;
}

/// Perform an operation having the signature
/// i8* (i8*)
/// where a null input causes a no-op and returns null.
Expand All @@ -2118,10 +2125,8 @@ static llvm::Value *emitARCValueOperation(
if (isa<llvm::ConstantPointerNull>(value))
return value;

if (!fn) {
fn = CGF.CGM.getIntrinsic(IntID);
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(IntID, CGF.CGM);

// Cast the argument to 'id'.
llvm::Type *origType = returnType ? returnType : value->getType();
Expand All @@ -2140,10 +2145,8 @@ static llvm::Value *emitARCValueOperation(
static llvm::Value *emitARCLoadOperation(CodeGenFunction &CGF, Address addr,
llvm::Function *&fn,
llvm::Intrinsic::ID IntID) {
if (!fn) {
fn = CGF.CGM.getIntrinsic(IntID);
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(IntID, CGF.CGM);

// Cast the argument to 'id*'.
llvm::Type *origType = addr.getElementType();
Expand All @@ -2168,10 +2171,8 @@ static llvm::Value *emitARCStoreOperation(CodeGenFunction &CGF, Address addr,
bool ignored) {
assert(addr.getElementType() == value->getType());

if (!fn) {
fn = CGF.CGM.getIntrinsic(IntID);
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(IntID, CGF.CGM);

llvm::Type *origType = value->getType();

Expand All @@ -2193,10 +2194,8 @@ static void emitARCCopyOperation(CodeGenFunction &CGF, Address dst, Address src,
llvm::Intrinsic::ID IntID) {
assert(dst.getType() == src.getType());

if (!fn) {
fn = CGF.CGM.getIntrinsic(IntID);
setARCRuntimeFunctionLinkage(CGF.CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(IntID, CGF.CGM);

llvm::Value *args[] = {
CGF.Builder.CreateBitCast(dst.getPointer(), CGF.Int8PtrPtrTy),
Expand Down Expand Up @@ -2340,13 +2339,19 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
// retainRV or claimRV calls in the IR. We currently do this only when the
// optimization level isn't -O0 since global-isel, which is currently run at
// -O0, doesn't know about the operand bundle.
ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
llvm::Function *&EP = IsRetainRV
? EPs.objc_retainAutoreleasedReturnValue
: EPs.objc_unsafeClaimAutoreleasedReturnValue;
llvm::Intrinsic::ID IID =
IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue
: llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;
EP = getARCIntrinsic(IID, CGF.CGM);

// FIXME: Do this when the target isn't aarch64.
if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
CGF.CGM.getTarget().getTriple().isAArch64()) {
llvm::Value *bundleArgs[] = {llvm::ConstantInt::get(
CGF.Int64Ty,
llvm::objcarc::getAttachedCallOperandBundleEnum(IsRetainRV))};
llvm::Value *bundleArgs[] = {EP};
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
auto *oldCall = cast<llvm::CallBase>(value);
llvm::CallBase *newCall = llvm::CallBase::addOperandBundle(
Expand All @@ -2362,13 +2367,6 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
CGF.CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail();
llvm::CallInst::TailCallKind tailKind =
isNoTail ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None;
ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
llvm::Function *&EP = IsRetainRV
? EPs.objc_retainAutoreleasedReturnValue
: EPs.objc_unsafeClaimAutoreleasedReturnValue;
llvm::Intrinsic::ID IID =
IsRetainRV ? llvm::Intrinsic::objc_retainAutoreleasedReturnValue
: llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue;
return emitARCValueOperation(CGF, value, nullptr, EP, IID, tailKind);
}

Expand Down Expand Up @@ -2401,10 +2399,8 @@ void CodeGenFunction::EmitARCRelease(llvm::Value *value,
if (isa<llvm::ConstantPointerNull>(value)) return;

llvm::Function *&fn = CGM.getObjCEntrypoints().objc_release;
if (!fn) {
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_release);
setARCRuntimeFunctionLinkage(CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(llvm::Intrinsic::objc_release, CGM);

// Cast the argument to 'id'.
value = Builder.CreateBitCast(value, Int8PtrTy);
Expand Down Expand Up @@ -2447,10 +2443,8 @@ llvm::Value *CodeGenFunction::EmitARCStoreStrongCall(Address addr,
assert(addr.getElementType() == value->getType());

llvm::Function *&fn = CGM.getObjCEntrypoints().objc_storeStrong;
if (!fn) {
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_storeStrong);
setARCRuntimeFunctionLinkage(CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(llvm::Intrinsic::objc_storeStrong, CGM);

llvm::Value *args[] = {
Builder.CreateBitCast(addr.getPointer(), Int8PtrPtrTy),
Expand Down Expand Up @@ -2603,10 +2597,8 @@ void CodeGenFunction::EmitARCInitWeak(Address addr, llvm::Value *value) {
/// Essentially objc_storeWeak(addr, nil).
void CodeGenFunction::EmitARCDestroyWeak(Address addr) {
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_destroyWeak;
if (!fn) {
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_destroyWeak);
setARCRuntimeFunctionLinkage(CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(llvm::Intrinsic::objc_destroyWeak, CGM);

// Cast the argument to 'id*'.
addr = Builder.CreateBitCast(addr, Int8PtrPtrTy);
Expand Down Expand Up @@ -2651,10 +2643,8 @@ void CodeGenFunction::emitARCMoveAssignWeak(QualType Ty, Address DstAddr,
/// call i8* \@objc_autoreleasePoolPush(void)
llvm::Value *CodeGenFunction::EmitObjCAutoreleasePoolPush() {
llvm::Function *&fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPush;
if (!fn) {
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush);
setARCRuntimeFunctionLinkage(CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPush, CGM);

return EmitNounwindRuntimeCall(fn);
}
Expand All @@ -2679,10 +2669,8 @@ void CodeGenFunction::EmitObjCAutoreleasePoolPop(llvm::Value *value) {
EmitRuntimeCallOrInvoke(fn, value);
} else {
llvm::FunctionCallee &fn = CGM.getObjCEntrypoints().objc_autoreleasePoolPop;
if (!fn) {
fn = CGM.getIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop);
setARCRuntimeFunctionLinkage(CGM, fn);
}
if (!fn)
fn = getARCIntrinsic(llvm::Intrinsic::objc_autoreleasePoolPop, CGM);

EmitRuntimeCall(fn, value);
}
Expand Down
20 changes: 10 additions & 10 deletions clang/test/CodeGenObjC/arc-rv-attr.m
Expand Up @@ -10,7 +10,7 @@ void test_assign() {
}
// CHECK-LABEL: define{{.*}} void @test_assign()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
Expand All @@ -25,7 +25,7 @@ void test_assign_assign() {
// CHECK-LABEL: define{{.*}} void @test_assign_assign()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
Expand All @@ -44,7 +44,7 @@ void test_strong_assign_assign() {
// CHECK-LABEL: define{{.*}} void @test_strong_assign_assign()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[Y]]
Expand All @@ -67,7 +67,7 @@ void test_assign_strong_assign() {
// CHECK-LABEL: define{{.*}} void @test_assign_strong_assign()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[Y]]
Expand All @@ -87,7 +87,7 @@ void test_init() {
}
// CHECK-LABEL: define{{.*}} void @test_init()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
Expand All @@ -102,7 +102,7 @@ void test_init_assignment() {
// CHECK-LABEL: define{{.*}} void @test_init_assignment()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
Expand All @@ -120,7 +120,7 @@ void test_strong_init_assignment() {
// CHECK-LABEL: define{{.*}} void @test_strong_init_assignment()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: store i8* [[T1]], i8** [[X]]
Expand All @@ -140,7 +140,7 @@ void test_init_strong_assignment() {
// CHECK-LABEL: define{{.*}} void @test_init_strong_assignment()
// CHECK: [[X:%.*]] = alloca i8*
// CHECK: [[Y:%.*]] = alloca i8*
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 0) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
// CHECK-NEXT: [[OLD:%.*]] = load i8*, i8** [[X]]
Expand All @@ -159,15 +159,15 @@ void test_ignored() {
makeA();
}
// CHECK-LABEL: define{{.*}} void @test_ignored()
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: ret void

void test_cast_to_void() {
(void) makeA();
}
// CHECK-LABEL: define{{.*}} void @test_cast_to_void()
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i64 1) ]
// CHECK: [[T0:%.*]] = call [[A]]* @makeA() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.noop.use({{.*}} [[T0]])
// CHECK-NEXT: ret void

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGenObjCXX/arc-rv-attr.mm
Expand Up @@ -3,7 +3,7 @@
id foo(void);

// CHECK-LABEL: define{{.*}} void @_Z14test_list_initv(
// CHECK: %[[CALL1:.*]] = call i8* @_Z3foov() [ "clang.arc.attachedcall"(i64 0) ]
// CHECK: %[[CALL1:.*]] = call i8* @_Z3foov() [ "clang.arc.attachedcall"(i8* (i8*)* @llvm.objc.retainAutoreleasedReturnValue) ]
// CHECK: call i8* @llvm.objc.retain(i8* %[[CALL1]])

void test_list_init() {
Expand Down

0 comments on commit 59cc39a

Please sign in to comment.