From 41b1e97b12c1407e40d8e5081bf1f9cf183934b0 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka Date: Mon, 3 Aug 2020 13:25:25 -0700 Subject: [PATCH] [CodeGen][ObjC] Mark calls to objc_unsafeClaimAutoreleasedReturnValue as notail on x86-64 This is needed because the epilogue code inserted before tail calls on x86-64 breaks the handshake between the caller and callee. Calls to objc_retainAutoreleasedReturnValue used to have the same problem, which was fixed in https://reviews.llvm.org/D59656. rdar://problem/66029552 Differential Revision: https://reviews.llvm.org/D84540 --- clang/lib/CodeGen/CGObjC.cpp | 14 +++++++++----- clang/lib/CodeGen/TargetInfo.cpp | 6 ++---- clang/lib/CodeGen/TargetInfo.h | 8 +++----- clang/test/CodeGenObjC/arc-unsafeclaim.m | 30 ++++++++++++++++++------------ 4 files changed, 32 insertions(+), 26 deletions(-) diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index cd2b84f..26dfb62 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -2250,8 +2250,7 @@ llvm::Value * 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 @@ CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) { 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.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 9cd63eb..f31d432 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -2404,10 +2404,8 @@ public: } /// 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/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h index 1152cab..0df9667 100644 --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -163,11 +163,9 @@ public: 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/test/CodeGenObjC/arc-unsafeclaim.m b/clang/test/CodeGenObjC/arc-unsafeclaim.m index a8011e0..40f1f16 100644 --- 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 @@ void test_assign() { // 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 @@ void test_assign_assign() { // 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 @@ void test_init() { // 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 @@ void test_init_assignment() { // 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 @@ void test_ignored() { // 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 @@ void test_cast_to_void() { // 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 -- 2.7.4