1; RUN: opt -S -objc-arc < %s | FileCheck %s
2
3; Handle a retain+release pair entirely contained within a split loop backedge.
4; rdar://11256239
5
6; CHECK-LABEL: define void @test0(
7; CHECK: call i8* @objc_retain(i8* %call) [[NUW:#[0-9]+]]
8; CHECK: call i8* @objc_retain(i8* %call) [[NUW]]
9; CHECK: call i8* @objc_retain(i8* %cond) [[NUW]]
10; CHECK: call void @objc_release(i8* %call) [[NUW]]
11; CHECK: call void @objc_release(i8* %call) [[NUW]]
12; CHECK: call void @objc_release(i8* %cond) [[NUW]]
13define void @test0() {
14entry:
15  br label %while.body
16
17while.body:                                       ; preds = %while.cond
18  %call = invoke i8* @returner()
19          to label %invoke.cont unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0
20
21invoke.cont:                                      ; preds = %while.body
22  %t0 = call i8* @objc_retain(i8* %call) nounwind
23  %t1 = call i8* @objc_retain(i8* %call) nounwind
24  %call.i1 = invoke i8* @returner()
25          to label %invoke.cont1 unwind label %lpad
26
27invoke.cont1:                                     ; preds = %invoke.cont
28  %cond = select i1 undef, i8* null, i8* %call
29  %t2 = call i8* @objc_retain(i8* %cond) nounwind
30  call void @objc_release(i8* %call) nounwind
31  call void @objc_release(i8* %call) nounwind
32  call void @use_pointer(i8* %cond)
33  call void @objc_release(i8* %cond) nounwind
34  br label %while.body
35
36lpad:                                             ; preds = %invoke.cont, %while.body
37  %t4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__objc_personality_v0 to i8*)
38          catch i8* null
39  ret void
40}
41
42declare i8* @returner()
43declare i32 @__objc_personality_v0(...)
44declare void @objc_release(i8*)
45declare i8* @objc_retain(i8*)
46declare void @use_pointer(i8*)
47
48!0 = !{}
49
50; CHECK: attributes [[NUW]] = { nounwind }
51