llvm/llvm/test/Transforms/ObjCARC/cfg-hazards.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=objc-arc < %s | FileCheck %s
; rdar://9503416

; Detect loop boundaries and don't move retains and releases
; across them.

declare void @use_pointer(ptr)
declare ptr @llvm.objc.retain(ptr)
declare void @llvm.objc.release(ptr)
declare void @callee()
declare void @block_callee(ptr)

define void @test0(ptr %digits) {
; CHECK-LABEL: @test0(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0:[0-9]+]]
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 12
; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK:       for.end:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind
  call void @use_pointer(ptr %digits)
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
  call void @use_pointer(ptr %digits)
  %inc = add i64 %upcDigitIndex.01, 1
  %cmp = icmp ult i64 %inc, 12
  br i1 %cmp, label %for.body, label %for.end

for.end:                                          ; preds = %for.body
  call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test1(ptr %digits) {
; CHECK-LABEL: @test1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 12
; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK:       for.end:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
  call void @use_pointer(ptr %digits)
  call void @use_pointer(ptr %digits)
  %inc = add i64 %upcDigitIndex.01, 1
  %cmp = icmp ult i64 %inc, 12
  br i1 %cmp, label %for.body, label %for.end

for.end:                                          ; preds = %for.body
  call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test2(ptr %digits) {
; CHECK-LABEL: @test2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1
; CHECK-NEXT:    [[CMP:%.*]] = icmp ult i64 [[INC]], 12
; CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]]
; CHECK:       for.end:
; CHECK-NEXT:    call void @use_pointer(ptr [[DIGITS]])
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind
  br label %for.body

for.body:                                         ; preds = %for.body, %entry
  %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ]
  call void @use_pointer(ptr %digits)
  %inc = add i64 %upcDigitIndex.01, 1
  %cmp = icmp ult i64 %inc, 12
  br i1 %cmp, label %for.body, label %for.end

for.end:                                          ; preds = %for.body
  call void @use_pointer(ptr %digits)
  call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0
  ret void
}

; Delete nested retain+release pairs around loops.
define void @test3(ptr %a) nounwind {
; CHECK-LABEL: @test3(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  call void @callee()
  store i8 0, ptr %a
  br i1 undef, label %loop, label %exit

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test4(ptr %a) nounwind {
; CHECK-LABEL: @test4(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br label [[MORE:%.*]]
; CHECK:       more:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    store i8 0, ptr [[A]], align 1
; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br label %more

more:
  call void @callee()
  call void @callee()
  store i8 0, ptr %a
  br i1 undef, label %loop, label %exit

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test5(ptr %a) nounwind {
; CHECK-LABEL: @test5(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    call void @use_pointer(ptr [[A]])
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  call void @callee()
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @use_pointer(ptr %a)
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test6(ptr %a) nounwind {
; CHECK-LABEL: @test6(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    call void @use_pointer(ptr [[A]])
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  call void @callee()
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @use_pointer(ptr %a)
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test7(ptr %a) nounwind {
; CHECK-LABEL: @test7(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    call void @use_pointer(ptr [[A]])
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  call void @callee()
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  call void @use_pointer(ptr %a)
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test8(ptr %a) nounwind {
; CHECK-LABEL: @test8(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    call void @use_pointer(ptr [[A]])
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  call void @callee()
  call void @use_pointer(ptr %a)
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test9(ptr %a) nounwind {
; CHECK-LABEL: @test9(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    call void @use_pointer(ptr [[A:%.*]])
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  call void @use_pointer(ptr %a)
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test10(ptr %a) nounwind {
; CHECK-LABEL: @test10(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  call void @callee()
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

define void @test11(ptr %a) nounwind {
; CHECK-LABEL: @test11(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    br label [[MORE]]
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  br label %more

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

; Don't delete anything if they're not balanced.

define void @test12(ptr %a) nounwind {
; CHECK-LABEL: @test12(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    [[INNER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    br i1 undef, label [[TRUE:%.*]], label [[MORE:%.*]]
; CHECK:       true:
; CHECK-NEXT:    ret void
; CHECK:       more:
; CHECK-NEXT:    br i1 undef, label [[EXIT:%.*]], label [[LOOP]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]]
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  br i1 undef, label %true, label %more

true:
  ret void

more:
  br i1 undef, label %exit, label %loop

exit:
  call void @llvm.objc.release(ptr %a) nounwind
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

; Do not improperly pair retains in a for loop with releases outside of a for
; loop when the proper pairing is disguised by a separate provenance represented
; by an alloca.
; rdar://12969722

define void @test13(ptr %a) nounwind {
; CHECK-LABEL: @test13(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[BLOCK:%.*]] = alloca ptr, align 8
; CHECK-NEXT:    [[A1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    br label [[LOOP:%.*]]
; CHECK:       loop:
; CHECK-NEXT:    [[A2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]]
; CHECK-NEXT:    store ptr [[A]], ptr [[BLOCK]], align 8
; CHECK-NEXT:    call void @block_callee(ptr [[BLOCK]])
; CHECK-NEXT:    [[RELOADED_A:%.*]] = load ptr, ptr [[BLOCK]], align 8
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[RELOADED_A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    br i1 undef, label [[LOOP]], label [[EXIT:%.*]]
; CHECK:       exit:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %block = alloca ptr
  %a1 = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  br label %loop

loop:
  %a2 = tail call ptr @llvm.objc.retain(ptr %a) nounwind
  store ptr %a, ptr %block, align 8
  call void @block_callee(ptr %block)
  %reloaded_a = load ptr, ptr %block, align 8
  call void @llvm.objc.release(ptr %reloaded_a) nounwind, !clang.imprecise_release !0
  br i1 undef, label %loop, label %exit

exit:
  call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0
  ret void
}

; The retain call in the entry block shouldn't be moved to the loop body.

define void @test14(ptr %val0, i8 %val1) {
; CHECK-LABEL: @test14(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[V1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL0:%.*]]) #[[ATTR0]]
; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[VAL0]], null
; CHECK-NEXT:    br i1 [[CMP]], label [[IF_END27:%.*]], label [[IF_THEN:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i8 [[VAL1:%.*]], 1
; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
; CHECK:       for.cond:
; CHECK-NEXT:    [[CMP6:%.*]] = icmp eq i8 [[VAL1]], 2
; CHECK-NEXT:    br i1 [[CMP6]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]]
; CHECK:       for.body:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    [[TOBOOL9:%.*]] = icmp eq i8 [[VAL1]], 0
; CHECK-NEXT:    br i1 [[TOBOOL9]], label [[FOR_COND:%.*]], label [[IF_THEN10:%.*]]
; CHECK:       if.then10:
; CHECK-NEXT:    br label [[FOR_END:%.*]]
; CHECK:       for.end.loopexit:
; CHECK-NEXT:    br label [[FOR_END]]
; CHECK:       for.end:
; CHECK-NEXT:    call void @callee()
; CHECK-NEXT:    call void @use_pointer(ptr [[V1]])
; CHECK-NEXT:    br label [[IF_END27]]
; CHECK:       if.end27:
; CHECK-NEXT:    call void @llvm.objc.release(ptr [[V1]]) #[[ATTR0]], !clang.imprecise_release !0
; CHECK-NEXT:    ret void
;
entry:
  %v1 = tail call ptr @llvm.objc.retain(ptr %val0)
  %cmp = icmp eq ptr %val0, null
  br i1 %cmp, label %if.end27, label %if.then

if.then:
  %tobool = icmp eq i8 %val1, 1
  br label %for.body

for.cond:
  %cmp6 = icmp eq i8 %val1, 2
  br i1 %cmp6, label %for.body, label %for.end.loopexit

for.body:
  call void @callee()
  %tobool9 = icmp eq i8 %val1, 0
  br i1 %tobool9, label %for.cond, label %if.then10

if.then10:
  br label %for.end

for.end.loopexit:
  br label %for.end

for.end:
  call void @callee()
  call void @use_pointer(ptr %v1)
  br label %if.end27

if.end27:
  call void @llvm.objc.release(ptr %v1) #0, !clang.imprecise_release !0
  ret void
}


!0 = !{}