1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00
llvm-mirror/test/Transforms/ObjCARC/post-inlining.ll
Francis Visoiu Mistrih 11150876b9 [ObjC][ARC] Ignore lifetime markers between *ReturnValue calls
When eliminating a pair of

`llvm.objc.autoreleaseReturnValue`

followed by

`llvm.objc.retainAutoreleasedReturnValue`

we need to make sure that the instructions in between are safe to
ignore.

Other than bitcasts and useless GEPs, it's also safe to ignore lifetime
markers for both static allocas (lifetime.start/lifetime.end) and dynamic
allocas (stacksave/stackrestore).

These get added by the inliner as part of the return sequence and can
prevent the transformation from happening in practice.

Differential Revision: https://reviews.llvm.org/D69833
2019-11-05 06:39:22 -08:00

113 lines
3.4 KiB
LLVM

; RUN: opt -S -objc-arc < %s | FileCheck %s
declare void @use_pointer(i8*)
declare i8* @returner()
declare i8* @llvm.objc.retain(i8*)
declare i8* @llvm.objc.autoreleaseReturnValue(i8*)
declare i8* @llvm.objc.retainAutoreleasedReturnValue(i8*)
; Clean up residue left behind after inlining.
; CHECK-LABEL: define void @test0(
; CHECK: entry:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test0(i8* %call.i) {
entry:
%0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind
%1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %0) nounwind
ret void
}
; Same as test0, but with slightly different use arrangements.
; CHECK-LABEL: define void @test1(
; CHECK: entry:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test1(i8* %call.i) {
entry:
%0 = tail call i8* @llvm.objc.retain(i8* %call.i) nounwind
%1 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
ret void
}
; Delete a retainRV+autoreleaseRV even if the pointer is used.
; CHECK-LABEL: define void @test24(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use_pointer(i8* %p)
; CHECK-NEXT: ret void
; CHECK-NEXT: }
define void @test24(i8* %p) {
entry:
call i8* @llvm.objc.autoreleaseReturnValue(i8* %p) nounwind
call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %p) nounwind
call void @use_pointer(i8* %p)
ret void
}
; Check that we can delete the autoreleaseRV+retainAutoreleasedRV pair even in
; presence of instructions added by the inliner as part of the return sequence.
; 1) Noop instructions: bitcasts and zero-indices GEPs.
; CHECK-LABEL: define i8* @testNoop(
; CHECK: entry:
; CHECK-NEXT: %noop0 = bitcast i8* %call.i to i64*
; CHECK-NEXT: %noop1 = getelementptr i8, i8* %call.i, i32 0
; CHECK-NEXT: ret i8* %call.i
; CHECK-NEXT: }
define i8* @testNoop(i8* %call.i) {
entry:
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
%noop0 = bitcast i8* %call.i to i64*
%noop1 = getelementptr i8, i8* %call.i, i32 0
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
ret i8* %call.i
}
; 2) Lifetime markers.
declare void @llvm.lifetime.start.p0i8(i64, i8*)
declare void @llvm.lifetime.end.p0i8(i64, i8*)
; CHECK-LABEL: define i8* @testLifetime(
; CHECK: entry:
; CHECK-NEXT: %obj = alloca i8
; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj)
; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj)
; CHECK-NEXT: ret i8* %call.i
; CHECK-NEXT: }
define i8* @testLifetime(i8* %call.i) {
entry:
%obj = alloca i8
call void @llvm.lifetime.start.p0i8(i64 8, i8* %obj)
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
call void @llvm.lifetime.end.p0i8(i64 8, i8* %obj)
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
ret i8* %call.i
}
; 3) Dynamic alloca markers.
declare i8* @llvm.stacksave()
declare void @llvm.stackrestore(i8*)
; CHECK-LABEL: define i8* @testStack(
; CHECK: entry:
; CHECK-NEXT: %save = tail call i8* @llvm.stacksave()
; CHECK-NEXT: %obj = alloca i8, i8 %arg
; CHECK-NEXT: call void @llvm.stackrestore(i8* %save)
; CHECK-NEXT: ret i8* %call.i
; CHECK-NEXT: }
define i8* @testStack(i8* %call.i, i8 %arg) {
entry:
%save = tail call i8* @llvm.stacksave()
%obj = alloca i8, i8 %arg
%0 = tail call i8* @llvm.objc.autoreleaseReturnValue(i8* %call.i) nounwind
call void @llvm.stackrestore(i8* %save)
%1 = tail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* %call.i) nounwind
ret i8* %call.i
}