Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions clang/lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2415,9 +2415,7 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,
emitAutoreleasedReturnValueMarker(CGF);

// Add operand bundle "clang.arc.attachedcall" to the call instead of emitting
// 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.
// retainRV or claimRV calls in the IR.
ObjCEntrypoints &EPs = CGF.CGM.getObjCEntrypoints();
llvm::Function *&EP = IsRetainRV
? EPs.objc_retainAutoreleasedReturnValue
Expand All @@ -2429,11 +2427,9 @@ static llvm::Value *emitOptimizedARCReturnCall(llvm::Value *value,

llvm::Triple::ArchType Arch = CGF.CGM.getTriple().getArch();

// FIXME: Do this on all targets and at -O0 too. This can be enabled only if
// the target backend knows how to handle the operand bundle.
if (CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
(Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::x86_64)) {
if ((CGF.CGM.getCodeGenOpts().OptimizationLevel > 0 &&
Arch == llvm::Triple::x86_64) ||
Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32) {
llvm::Value *bundleArgs[] = {EP};
llvm::OperandBundleDef OB("clang.arc.attachedcall", bundleArgs);
auto *oldCall = cast<llvm::CallBase>(value);
Expand Down
23 changes: 22 additions & 1 deletion clang/test/CodeGenObjC/arc-arm.m
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
// RUN: %clang_cc1 -triple armv7-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-ios -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple arm64-apple-ios -emit-llvm -fblocks -fobjc-arc -o - %s | FileCheck %s -check-prefix=ARM64-ATTACHED

// use an autorelease marker on ARM64.

id test0(void) {
extern id test0_helper(void);
// CHECK: [[T0:%.*]] = call [[CC:(arm_aapcscc )?]]ptr @test0_helper()
// CHECK-NEXT: ret ptr [[T0]]
// ARM64-ATTACHED: %call1 = call ptr @test0_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ARM64-ATTACHED: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
// ARM64-ATTACHED: call void (...) @llvm.objc.clang.arc.noop.use(ptr %call1) #2
// ARM64-ATTACHED: %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call1) #2
// ARM64-ATTACHED: ret ptr %0
return test0_helper();
}

Expand All @@ -18,6 +23,12 @@ void test1(void) {
// CHECK-NEXT: store ptr [[T1]],
// CHECK-NEXT: call [[CC]]void @llvm.objc.storeStrong(
// CHECK-NEXT: ret void
// ARM64-ATTACHED: %call1 = call ptr @test1_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ARM64-ATTACHED: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
// ARM64-ATTACHED: call void (...) @llvm.objc.clang.arc.noop.use(ptr %call1) #2
// ARM64-ATTACHED: store ptr %call1,
// ARM64-ATTACHED: call void @llvm.objc.storeStrong(
// ARM64-ATTACHED: ret void
id x = test1_helper();
}

Expand All @@ -26,12 +37,22 @@ void test1(void) {
extern A *test2_helper(void);
// CHECK: [[T0:%.*]] = call [[CC]]ptr @test2_helper()
// CHECK-NEXT: ret ptr [[T0]]
// ARM64-ATTACHED: %call1 = call ptr @test2_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ARM64-ATTACHED: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
// ARM64-ATTACHED: call void (...) @llvm.objc.clang.arc.noop.use(ptr %call1) #2
// ARM64-ATTACHED: %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call1) #2
// ARM64-ATTACHED: ret ptr %0
return test2_helper();
}

id test3(void) {
extern A *test3_helper(void);
// CHECK: [[T0:%.*]] = call [[CC]]ptr @test3_helper()
// CHECK-NEXT: ret ptr [[T0]]
// ARM64-ATTACHED: %call1 = call ptr @test3_helper() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ARM64-ATTACHED: call void asm sideeffect "mov\09fp, fp\09\09// marker for objc_retainAutoreleaseReturnValue", ""()
// ARM64-ATTACHED: call void (...) @llvm.objc.clang.arc.noop.use(ptr %call1) #2
// ARM64-ATTACHED: %0 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %call1) #2
// ARM64-ATTACHED: ret ptr %0
return test3_helper();
}
52 changes: 31 additions & 21 deletions clang/test/CodeGenObjC/arc-unsafeclaim.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// 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

// Make sure it works on ARM64.
// 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
// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=ATTACHED-CALL

// Make sure it works on ARM.
// 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
Expand Down Expand Up @@ -41,8 +41,9 @@ void test_assign(void) {
// DISABLED-NEXT: [[T2:%.*]] = {{.*}}call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr [[T0]])

// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_assign_assign(void) {
__unsafe_unretained id x, y;
Expand All @@ -62,8 +63,9 @@ void test_assign_assign(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_assign()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_strong_assign_assign(void) {
__strong id x;
Expand All @@ -88,8 +90,9 @@ void test_strong_assign_assign(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_assign_assign()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_assign_strong_assign(void) {
__unsafe_unretained id x;
Expand All @@ -114,8 +117,9 @@ void test_assign_strong_assign(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_assign_strong_assign()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_init(void) {
__unsafe_unretained id x = makeA();
Expand All @@ -131,8 +135,9 @@ void test_init(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_init()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_init_assignment(void) {
__unsafe_unretained id x;
Expand All @@ -152,8 +157,9 @@ void test_init_assignment(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_init_assignment()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_strong_init_assignment(void) {
__unsafe_unretained id x;
Expand All @@ -175,8 +181,9 @@ void test_strong_init_assignment(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_strong_init_assignment()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_init_strong_assignment(void) {
__strong id x;
Expand All @@ -200,8 +207,9 @@ void test_init_strong_assignment(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_init_strong_assignment()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.retainAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_ignored(void) {
makeA();
Expand All @@ -214,8 +222,9 @@ void test_ignored(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_ignored()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])

void test_cast_to_void(void) {
(void) makeA();
Expand All @@ -228,8 +237,9 @@ void test_cast_to_void(void) {
// CHECK-NEXT: ret void

// ATTACHED-CALL-LABEL: define{{.*}} void @test_cast_to_void()
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ],
// ATTACHED-CALL: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])
// ATTACHED-CALL: [[T0:%.*]] = call ptr @makeA() [ "clang.arc.attachedcall"(ptr @llvm.objc.unsafeClaimAutoreleasedReturnValue) ]
// ATTACHED-CALL-NEXT: call void asm sideeffect
// ATTACHED-CALL-NEXT: call void (...) @llvm.objc.clang.arc.noop.use(ptr [[T0]])


// This is always at the end of the module.
Expand Down
5 changes: 5 additions & 0 deletions llvm/lib/Target/AArch64/AArch64FastISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/FastISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
Expand Down Expand Up @@ -3159,6 +3160,10 @@ bool AArch64FastISel::fastLowerCall(CallLoweringInfo &CLI) {
CLI.CB->getOperandBundle(LLVMContext::OB_kcfi))
return false;

// Allow SelectionDAG isel to handle clang.arc.attachedcall operand bundle.
if (CLI.CB && objcarc::hasAttachedCallOpBundle(CLI.CB))
return false;

// Allow SelectionDAG isel to handle tail calls.
if (IsTailCall)
return false;
Expand Down
Loading
Loading