diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -2250,8 +2250,7 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { emitAutoreleasedReturnValueMarker(*this); llvm::CallInst::TailCallKind tailKind = - CGM.getTargetCodeGenInfo() - .shouldSuppressTailCallsOfRetainAutoreleasedReturnValue() + CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail() ? llvm::CallInst::TCK_NoTail : llvm::CallInst::TCK_None; return emitARCValueOperation( @@ -2270,9 +2269,14 @@ llvm::Value * CodeGenFunction::EmitARCUnsafeClaimAutoreleasedReturnValue(llvm::Value *value) { emitAutoreleasedReturnValueMarker(*this); - return emitARCValueOperation(*this, value, nullptr, - CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue, - llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue); + llvm::CallInst::TailCallKind tailKind = + CGM.getTargetCodeGenInfo().markARCOptimizedReturnCallsAsNoTail() + ? llvm::CallInst::TCK_NoTail + : llvm::CallInst::TCK_None; + return emitARCValueOperation( + *this, value, nullptr, + CGM.getObjCEntrypoints().objc_unsafeClaimAutoreleasedReturnValue, + llvm::Intrinsic::objc_unsafeClaimAutoreleasedReturnValue, tailKind); } /// Release the given object. diff --git a/clang/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -163,11 +163,9 @@ return ""; } - /// Determine whether a call to objc_retainAutoreleasedReturnValue should be - /// marked as 'notail'. - virtual bool shouldSuppressTailCallsOfRetainAutoreleasedReturnValue() const { - return false; - } + /// Determine whether a call to objc_retainAutoreleasedReturnValue or + /// objc_unsafeClaimAutoreleasedReturnValue should be marked as 'notail'. + virtual bool markARCOptimizedReturnCallsAsNoTail() const { return false; } /// Return a constant used by UBSan as a signature to identify functions /// possessing type information, or 0 if the platform is unsupported. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2404,10 +2404,8 @@ } /// Disable tail call on x86-64. The epilogue code before the tail jump blocks - /// the autoreleaseRV/retainRV optimization. - bool shouldSuppressTailCallsOfRetainAutoreleasedReturnValue() const override { - return true; - } + /// autoreleaseRV/retainRV and autoreleaseRV/unsafeClaimRV optimizations. + bool markARCOptimizedReturnCallsAsNoTail() const override { return true; } int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override { return 7; diff --git a/clang/test/CodeGenObjC/arc-unsafeclaim.m b/clang/test/CodeGenObjC/arc-unsafeclaim.m --- a/clang/test/CodeGenObjC/arc-unsafeclaim.m +++ b/clang/test/CodeGenObjC/arc-unsafeclaim.m @@ -1,16 +1,16 @@ // Make sure it works on x86-64. -// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED +// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-runtime=macosx-10.11 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-UNOPTIMIZED -check-prefix=NOTAIL-CALL // Make sure it works on x86-32. -// 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 +// 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 ARM. -// 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 -// RUN: %clang_cc1 -triple arm64-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED +// 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 -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL // Make sure it works on ARM64. -// 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 -// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED +// 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 +// RUN: %clang_cc1 -triple armv7-apple-ios9 -fobjc-runtime=ios-9.0 -fobjc-arc -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK -check-prefix=CHECK-OPTIMIZED -check-prefix=CALL // Make sure that it's implicitly disabled if the runtime version isn't high enough. // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-10.10 -fobjc-arc -emit-llvm -o - %s | FileCheck %s -check-prefix=DISABLED @@ -29,7 +29,8 @@ // CHECK: [[T0:%.*]] = call [[A:.*]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* // CHECK-NEXT: store i8* [[T4]], i8** [[X]] @@ -53,7 +54,8 @@ // CHECK: [[T0:%.*]] = call [[A]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* // CHECK-NEXT: store i8* [[T4]], i8** [[Y]] @@ -126,7 +128,8 @@ // CHECK: [[T0:%.*]] = call [[A]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* // CHECK-NEXT: store i8* [[T4]], i8** [[X]] @@ -144,7 +147,8 @@ // CHECK: [[T0:%.*]] = call [[A]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: [[T4:%.*]] = bitcast [[A]]* [[T3]] to i8* // CHECK-NEXT: store i8* [[T4]], i8** [[X]] @@ -212,7 +216,8 @@ // CHECK: [[T0:%.*]] = call [[A]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: ret void @@ -223,7 +228,8 @@ // CHECK: [[T0:%.*]] = call [[A]]* @makeA() // CHECK-MARKED-NEXT: call void asm sideeffect // CHECK-NEXT: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8* -// CHECK-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// NOTAIL-CALL-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) +// CALL-NEXT: [[T2:%.*]] = call i8* @llvm.objc.unsafeClaimAutoreleasedReturnValue(i8* [[T1]]) // CHECK-NEXT: bitcast i8* [[T2]] to [[A]]* // CHECK-NEXT: ret void