Skip to content

Commit df76f1e

Browse files
author
Chad Rosier
committed
Marking the objc_autoreleaseReturnValue and objc_retainAutoreleaseReturnValue
call sites as tail calls unconditionally. While it's theoretically true that this is just an optimization, it's an optimization that we very much want to happen even at -O0, or else ARC applications become substantially harder to debug. See r169796 for the llvm/fast-isel side of things. rdar://12553082 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@169996 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 21fa5d1 commit df76f1e

File tree

6 files changed

+18
-13
lines changed

6 files changed

+18
-13
lines changed

lib/CodeGen/CGObjC.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1725,7 +1725,8 @@ static llvm::Constant *createARCRuntimeFunction(CodeGenModule &CGM,
17251725
static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
17261726
llvm::Value *value,
17271727
llvm::Constant *&fn,
1728-
StringRef fnName) {
1728+
StringRef fnName,
1729+
bool isTailCall = false) {
17291730
if (isa<llvm::ConstantPointerNull>(value)) return value;
17301731

17311732
if (!fn) {
@@ -1742,6 +1743,8 @@ static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
17421743
// Call the function.
17431744
llvm::CallInst *call = CGF.Builder.CreateCall(fn, value);
17441745
call->setDoesNotThrow();
1746+
if (isTailCall)
1747+
call->setTailCall();
17451748

17461749
// Cast the result back to the original type.
17471750
return CGF.Builder.CreateBitCast(call, origType);
@@ -2054,7 +2057,8 @@ llvm::Value *
20542057
CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
20552058
return emitARCValueOperation(*this, value,
20562059
CGM.getARCEntrypoints().objc_autoreleaseReturnValue,
2057-
"objc_autoreleaseReturnValue");
2060+
"objc_autoreleaseReturnValue",
2061+
/*isTailCall*/ true);
20582062
}
20592063

20602064
/// Do a fused retain/autorelease of the given object.
@@ -2063,7 +2067,8 @@ llvm::Value *
20632067
CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
20642068
return emitARCValueOperation(*this, value,
20652069
CGM.getARCEntrypoints().objc_retainAutoreleaseReturnValue,
2066-
"objc_retainAutoreleaseReturnValue");
2070+
"objc_retainAutoreleaseReturnValue",
2071+
/*isTailCall*/ true);
20672072
}
20682073

20692074
/// Do a fused retain/autorelease of the given object.

test/CodeGenObjC/arc-blocks.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ void test0(id (^maker)(void)) {
1616
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) nounwind
1717
// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i32 ()*
1818
// CHECK-NEXT: [[T4:%.*]] = bitcast i32 ()* [[T3]] to i8*
19-
// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind
19+
// CHECK-NEXT: [[T5:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T4]]) nounwind
2020
// CHECK-NEXT: [[T6:%.*]] = bitcast i8* [[T5]] to i32 ()*
2121
// CHECK-NEXT: ret i32 ()* [[T6]]
2222
return ^{ return x; };
@@ -314,7 +314,7 @@ id test9(void) {
314314
// CHECK: load i8** getelementptr
315315
// CHECK-NEXT: bitcast i8*
316316
// CHECK-NEXT: call i8*
317-
// CHECK-NEXT: call i8* @objc_autoreleaseReturnValue
317+
// CHECK-NEXT: tail call i8* @objc_autoreleaseReturnValue
318318
// CHECK-NEXT: ret i8*
319319

320320
// CHECK: call i8* @test9_produce()

test/CodeGenObjC/arc-unopt.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
// CHECK: [[LD:%.*]] = load [[TEST0:%.*]]** @test0_helper
1111
// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST0]]* [[LD]] to i8*
12-
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]])
12+
// CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[T0]])
1313
// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to [[TEST0]]*
1414
// CHECK-NEXT: ret [[TEST0]]* [[T2]]
1515
}
@@ -19,7 +19,7 @@ id test1(void) {
1919
return test1_helper;
2020

2121
// CHECK: [[LD:%.*]] = load i8** @test1_helper
22-
// CHECK-NEXT: [[T0:%.*]] = call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]])
22+
// CHECK-NEXT: [[T0:%.*]] = tail call i8* @objc_retainAutoreleaseReturnValue(i8* [[LD]])
2323
// CHECK-NEXT: ret i8* [[T0]]
2424
}
2525

test/CodeGenObjC/arc-weak-property.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ @implementation WeakPropertyTest
2222
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]]
2323
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
2424
// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]])
25-
// CHECK-NEXT: [[T6:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
25+
// CHECK-NEXT: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
2626
// CHECK-NEXT: ret i8* [[T6]]
2727

2828
// CHECK: define internal void @"\01-[WeakPropertyTest setPROP:]"

test/CodeGenObjC/arc.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ id test1(id x) {
2929
// CHECK-NEXT: call void @objc_release(i8* [[T0]])
3030
// CHECK-NEXT: [[T1:%.*]] = load i8** [[X]]
3131
// CHECK-NEXT: call void @objc_release(i8* [[T1]])
32-
// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[RET]])
32+
// CHECK-NEXT: [[T1:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[RET]])
3333
// CHECK-NEXT: ret i8* [[T1]]
3434
id y;
3535
return y;
@@ -156,7 +156,7 @@ id test4() {
156156
// Retain/release elided.
157157
// CHECK-NEXT: bitcast
158158
// CHECK-NEXT: [[INIT:%.*]] = bitcast
159-
// CHECK-NEXT: [[RET:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[INIT]])
159+
// CHECK-NEXT: [[RET:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[INIT]])
160160

161161
// CHECK-NEXT: ret i8* [[RET]]
162162

@@ -1191,7 +1191,7 @@ id test52(void) {
11911191
// CHECK-NEXT: store i32 5, i32* [[X]],
11921192
// CHECK-NEXT: [[T0:%.*]] = load i32* [[X]],
11931193
// CHECK-NEXT: [[T1:%.*]] = call i8* @test52_helper(i32 [[T0]])
1194-
// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
1194+
// CHECK-NEXT: [[T2:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T1]])
11951195
// CHECK-NEXT: ret i8* [[T2]]
11961196
}
11971197

@@ -1292,7 +1292,7 @@ @implementation Test57
12921292
// CHECK-NEXT: [[T3:%.*]] = getelementptr inbounds i8* [[T2]], i64 [[T1]]
12931293
// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to i8**
12941294
// CHECK-NEXT: [[T5:%.*]] = call i8* @objc_loadWeakRetained(i8** [[T4]])
1295-
// CHECK-NEXT: [[T6:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
1295+
// CHECK-NEXT: [[T6:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[T5]])
12961296
// CHECK-NEXT: ret i8* [[T6]]
12971297

12981298
// CHECK: define internal i8* @"\01-[Test57 unsafe]"(

test/CodeGenObjC/objc-arc-container-subscripting.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ id func() {
1515
// CHECK: [[SIX:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[call]]) nounwind
1616
// CHECK: [[ARRAY_CASTED:%.*]] = bitcast %0** {{%.*}} to i8**
1717
// CHECK: call void @objc_storeStrong(i8** [[ARRAY_CASTED]], i8* null)
18-
// CHECK: [[EIGHT:%.*]] = call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
18+
// CHECK: [[EIGHT:%.*]] = tail call i8* @objc_autoreleaseReturnValue(i8* [[SIX]]) nounwind
1919
// CHECK: ret i8* [[EIGHT]]
2020

0 commit comments

Comments
 (0)