1; RUN: opt -S -objc-arc < %s | FileCheck %s
2; rdar://10210274
3
4%0 = type opaque
5
6declare i8* @objc_retain(i8*)
7
8declare void @objc_release(i8*)
9
10declare i8* @objc_autoreleaseReturnValue(i8*)
11
12; Don't delete the autorelease.
13
14; CHECK-LABEL: define %0* @test0(
15; CHECK:   @objc_retain
16; CHECK: .lr.ph:
17; CHECK-NOT: @objc_r
18; CHECK: @objc_autoreleaseReturnValue
19; CHECK-NOT: @objc_
20; CHECK: }
21define %0* @test0(%0* %buffer) nounwind {
22  %1 = bitcast %0* %buffer to i8*
23  %2 = tail call i8* @objc_retain(i8* %1) nounwind
24  br i1 undef, label %.lr.ph, label %._crit_edge
25
26.lr.ph:                                           ; preds = %.lr.ph, %0
27  br i1 false, label %.lr.ph, label %._crit_edge
28
29._crit_edge:                                      ; preds = %.lr.ph, %0
30  %3 = tail call i8* @objc_retain(i8* %1) nounwind
31  tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
32  %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
33  ret %0* %buffer
34}
35
36; Do delete the autorelease, even with the retain in a different block.
37
38; CHECK-LABEL: define %0* @test1(
39; CHECK-NOT: @objc
40; CHECK: }
41define %0* @test1() nounwind {
42  %buffer = call %0* @foo()
43  %1 = bitcast %0* %buffer to i8*
44  %2 = tail call i8* @objc_retain(i8* %1) nounwind
45  br i1 undef, label %.lr.ph, label %._crit_edge
46
47.lr.ph:                                           ; preds = %.lr.ph, %0
48  br i1 false, label %.lr.ph, label %._crit_edge
49
50._crit_edge:                                      ; preds = %.lr.ph, %0
51  %3 = tail call i8* @objc_retain(i8* %1) nounwind
52  tail call void @objc_release(i8* %1) nounwind, !clang.imprecise_release !0
53  %4 = tail call i8* @objc_autoreleaseReturnValue(i8* %1) nounwind
54  ret %0* %buffer
55}
56
57declare %0* @foo()
58
59!0 = !{}
60