diff options
| author | Dan Gohman <gohman@apple.com> | 2011-08-19 00:26:36 +0000 |
|---|---|---|
| committer | Dan Gohman <gohman@apple.com> | 2011-08-19 00:26:36 +0000 |
| commit | b38940135b38f256aad1840ce72fb76b73cd5568 (patch) | |
| tree | d669d47376687175b28ab5d9175bb55d288739c6 /llvm/test | |
| parent | c61f7659ba9d77b70cc7b620863e4bfbe6a3f13f (diff) | |
| download | bcm5719-llvm-b38940135b38f256aad1840ce72fb76b73cd5568.tar.gz bcm5719-llvm-b38940135b38f256aad1840ce72fb76b73cd5568.zip | |
Track a retain+release nesting level independently of the
known-incremented level, because the two concepts can be used
to prove the saftey of a retain+release removal in different
ways.
llvm-svn: 138016
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/Transforms/ObjCARC/basic.ll | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/llvm/test/Transforms/ObjCARC/basic.ll b/llvm/test/Transforms/ObjCARC/basic.ll index a6bbf8674b4..aeb4c88d0d3 100644 --- a/llvm/test/Transforms/ObjCARC/basic.ll +++ b/llvm/test/Transforms/ObjCARC/basic.ll @@ -1569,6 +1569,74 @@ if.end: ; preds = %entry, %if.then ret void } +; When there are adjacent retain+release pairs, the first one is +; known unnecessary because the presence of the second one means that +; the first one won't be deleting the object. + +; CHECK: define void @test57( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @objc_release(i8* %x) nounwind +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test57(i8* %x) nounwind { +entry: + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + ret void +} + +; An adjacent retain+release pair is sufficient even if it will be +; removed itself. + +; CHECK: define void @test58( +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test58(i8* %x) nounwind { +entry: + call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + call i8* @objc_retain(i8* %x) nounwind + call void @objc_release(i8* %x) nounwind + ret void +} + +; Don't delete the second retain+release pair in an adjacent set. + +; CHECK: define void @test59( +; CHECK-NEXT: entry: +; CHECK-NEXT: %0 = tail call i8* @objc_retain(i8* %x) nounwind +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @use_pointer(i8* %x) +; CHECK-NEXT: call void @objc_release(i8* %x) nounwind +; CHECK-NEXT: ret void +; CHECK-NEXT: } +define void @test59(i8* %x) nounwind { +entry: + %a = call i8* @objc_retain(i8* %x) nounwind + call void @objc_release(i8* %x) nounwind + %b = call i8* @objc_retain(i8* %x) nounwind + call void @use_pointer(i8* %x) + call void @use_pointer(i8* %x) + call void @objc_release(i8* %x) nounwind + ret void +} + declare void @bar(i32 ()*) ; A few real-world testcases. |

