1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=objc-arc < %s | FileCheck %s 3; rdar://9503416 4 5; Detect loop boundaries and don't move retains and releases 6; across them. 7 8declare void @use_pointer(ptr) 9declare ptr @llvm.objc.retain(ptr) 10declare void @llvm.objc.release(ptr) 11declare void @callee() 12declare void @block_callee(ptr) 13 14define void @test0(ptr %digits) { 15; CHECK-LABEL: @test0( 16; CHECK-NEXT: entry: 17; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0:[0-9]+]] 18; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 19; CHECK-NEXT: br label [[FOR_BODY:%.*]] 20; CHECK: for.body: 21; CHECK-NEXT: [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 22; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 23; CHECK-NEXT: [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1 24; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 12 25; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 26; CHECK: for.end: 27; CHECK-NEXT: call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0 28; CHECK-NEXT: ret void 29; 30entry: 31 %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind 32 call void @use_pointer(ptr %digits) 33 br label %for.body 34 35for.body: ; preds = %for.body, %entry 36 %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] 37 call void @use_pointer(ptr %digits) 38 %inc = add i64 %upcDigitIndex.01, 1 39 %cmp = icmp ult i64 %inc, 12 40 br i1 %cmp, label %for.body, label %for.end 41 42for.end: ; preds = %for.body 43 call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0 44 ret void 45} 46 47define void @test1(ptr %digits) { 48; CHECK-LABEL: @test1( 49; CHECK-NEXT: entry: 50; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0]] 51; CHECK-NEXT: br label [[FOR_BODY:%.*]] 52; CHECK: for.body: 53; CHECK-NEXT: [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 54; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 55; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 56; CHECK-NEXT: [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1 57; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 12 58; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 59; CHECK: for.end: 60; CHECK-NEXT: call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0 61; CHECK-NEXT: ret void 62; 63entry: 64 %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind 65 br label %for.body 66 67for.body: ; preds = %for.body, %entry 68 %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] 69 call void @use_pointer(ptr %digits) 70 call void @use_pointer(ptr %digits) 71 %inc = add i64 %upcDigitIndex.01, 1 72 %cmp = icmp ult i64 %inc, 12 73 br i1 %cmp, label %for.body, label %for.end 74 75for.end: ; preds = %for.body 76 call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0 77 ret void 78} 79 80define void @test2(ptr %digits) { 81; CHECK-LABEL: @test2( 82; CHECK-NEXT: entry: 83; CHECK-NEXT: [[TMP1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[DIGITS:%.*]]) #[[ATTR0]] 84; CHECK-NEXT: br label [[FOR_BODY:%.*]] 85; CHECK: for.body: 86; CHECK-NEXT: [[UPCDIGITINDEX_01:%.*]] = phi i64 [ 2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] 87; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 88; CHECK-NEXT: [[INC]] = add i64 [[UPCDIGITINDEX_01]], 1 89; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[INC]], 12 90; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 91; CHECK: for.end: 92; CHECK-NEXT: call void @use_pointer(ptr [[DIGITS]]) 93; CHECK-NEXT: call void @llvm.objc.release(ptr [[DIGITS]]) #[[ATTR0]], !clang.imprecise_release !0 94; CHECK-NEXT: ret void 95; 96entry: 97 %tmp1 = call ptr @llvm.objc.retain(ptr %digits) nounwind 98 br label %for.body 99 100for.body: ; preds = %for.body, %entry 101 %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] 102 call void @use_pointer(ptr %digits) 103 %inc = add i64 %upcDigitIndex.01, 1 104 %cmp = icmp ult i64 %inc, 12 105 br i1 %cmp, label %for.body, label %for.end 106 107for.end: ; preds = %for.body 108 call void @use_pointer(ptr %digits) 109 call void @llvm.objc.release(ptr %digits) nounwind, !clang.imprecise_release !0 110 ret void 111} 112 113; Delete nested retain+release pairs around loops. 114define void @test3(ptr %a, i1 %arg) nounwind { 115; CHECK-LABEL: @test3( 116; CHECK-NEXT: entry: 117; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 118; CHECK-NEXT: br label [[LOOP:%.*]] 119; CHECK: loop: 120; CHECK-NEXT: call void @callee() 121; CHECK-NEXT: store i8 0, ptr [[A]], align 1 122; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[EXIT:%.*]] 123; CHECK: exit: 124; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 125; CHECK-NEXT: ret void 126; 127entry: 128 %outer = call ptr @llvm.objc.retain(ptr %a) nounwind 129 %inner = call ptr @llvm.objc.retain(ptr %a) nounwind 130 br label %loop 131 132loop: 133 call void @callee() 134 store i8 0, ptr %a 135 br i1 %arg, label %loop, label %exit 136 137exit: 138 call void @llvm.objc.release(ptr %a) nounwind 139 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 140 ret void 141} 142 143define void @test4(ptr %a, i1 %arg) nounwind { 144; CHECK-LABEL: @test4( 145; CHECK-NEXT: entry: 146; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 147; CHECK-NEXT: br label [[LOOP:%.*]] 148; CHECK: loop: 149; CHECK-NEXT: br label [[MORE:%.*]] 150; CHECK: more: 151; CHECK-NEXT: call void @callee() 152; CHECK-NEXT: call void @callee() 153; CHECK-NEXT: store i8 0, ptr [[A]], align 1 154; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[EXIT:%.*]] 155; CHECK: exit: 156; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 157; CHECK-NEXT: ret void 158; 159entry: 160 %outer = call ptr @llvm.objc.retain(ptr %a) nounwind 161 %inner = call ptr @llvm.objc.retain(ptr %a) nounwind 162 br label %loop 163 164loop: 165 br label %more 166 167more: 168 call void @callee() 169 call void @callee() 170 store i8 0, ptr %a 171 br i1 %arg, label %loop, label %exit 172 173exit: 174 call void @llvm.objc.release(ptr %a) nounwind 175 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 176 ret void 177} 178 179define void @test5(ptr %a, i1 %arg) nounwind { 180; CHECK-LABEL: @test5( 181; CHECK-NEXT: entry: 182; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 183; CHECK-NEXT: call void @callee() 184; CHECK-NEXT: br label [[LOOP:%.*]] 185; CHECK: loop: 186; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 187; CHECK: true: 188; CHECK-NEXT: br label [[MORE]] 189; CHECK: more: 190; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 191; CHECK: exit: 192; CHECK-NEXT: call void @use_pointer(ptr [[A]]) 193; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 194; CHECK-NEXT: ret void 195; 196entry: 197 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 198 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 199 call void @callee() 200 br label %loop 201 202loop: 203 br i1 %arg, label %true, label %more 204 205true: 206 br label %more 207 208more: 209 br i1 %arg, label %exit, label %loop 210 211exit: 212 call void @use_pointer(ptr %a) 213 call void @llvm.objc.release(ptr %a) nounwind 214 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 215 ret void 216} 217 218define void @test6(ptr %a, i1 %arg) nounwind { 219; CHECK-LABEL: @test6( 220; CHECK-NEXT: entry: 221; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 222; CHECK-NEXT: br label [[LOOP:%.*]] 223; CHECK: loop: 224; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 225; CHECK: true: 226; CHECK-NEXT: call void @callee() 227; CHECK-NEXT: br label [[MORE]] 228; CHECK: more: 229; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 230; CHECK: exit: 231; CHECK-NEXT: call void @use_pointer(ptr [[A]]) 232; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 233; CHECK-NEXT: ret void 234; 235entry: 236 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 237 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 238 br label %loop 239 240loop: 241 br i1 %arg, label %true, label %more 242 243true: 244 call void @callee() 245 br label %more 246 247more: 248 br i1 %arg, label %exit, label %loop 249 250exit: 251 call void @use_pointer(ptr %a) 252 call void @llvm.objc.release(ptr %a) nounwind 253 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 254 ret void 255} 256 257define void @test7(ptr %a, i1 %arg) nounwind { 258; CHECK-LABEL: @test7( 259; CHECK-NEXT: entry: 260; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 261; CHECK-NEXT: call void @callee() 262; CHECK-NEXT: br label [[LOOP:%.*]] 263; CHECK: loop: 264; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 265; CHECK: true: 266; CHECK-NEXT: call void @use_pointer(ptr [[A]]) 267; CHECK-NEXT: br label [[MORE]] 268; CHECK: more: 269; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 270; CHECK: exit: 271; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 272; CHECK-NEXT: ret void 273; 274entry: 275 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 276 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 277 call void @callee() 278 br label %loop 279 280loop: 281 br i1 %arg, label %true, label %more 282 283true: 284 call void @use_pointer(ptr %a) 285 br label %more 286 287more: 288 br i1 %arg, label %exit, label %loop 289 290exit: 291 call void @llvm.objc.release(ptr %a) nounwind 292 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 293 ret void 294} 295 296define void @test8(ptr %a, i1 %arg) nounwind { 297; CHECK-LABEL: @test8( 298; CHECK-NEXT: entry: 299; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 300; CHECK-NEXT: br label [[LOOP:%.*]] 301; CHECK: loop: 302; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 303; CHECK: true: 304; CHECK-NEXT: call void @callee() 305; CHECK-NEXT: call void @use_pointer(ptr [[A]]) 306; CHECK-NEXT: br label [[MORE]] 307; CHECK: more: 308; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 309; CHECK: exit: 310; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 311; CHECK-NEXT: ret void 312; 313entry: 314 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 315 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 316 br label %loop 317 318loop: 319 br i1 %arg, label %true, label %more 320 321true: 322 call void @callee() 323 call void @use_pointer(ptr %a) 324 br label %more 325 326more: 327 br i1 %arg, label %exit, label %loop 328 329exit: 330 call void @llvm.objc.release(ptr %a) nounwind 331 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 332 ret void 333} 334 335define void @test9(ptr %a, i1 %arg) nounwind { 336; CHECK-LABEL: @test9( 337; CHECK-NEXT: entry: 338; CHECK-NEXT: br label [[LOOP:%.*]] 339; CHECK: loop: 340; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 341; CHECK: true: 342; CHECK-NEXT: call void @use_pointer(ptr [[A:%.*]]) 343; CHECK-NEXT: br label [[MORE]] 344; CHECK: more: 345; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 346; CHECK: exit: 347; CHECK-NEXT: ret void 348; 349entry: 350 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 351 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 352 br label %loop 353 354loop: 355 br i1 %arg, label %true, label %more 356 357true: 358 call void @use_pointer(ptr %a) 359 br label %more 360 361more: 362 br i1 %arg, label %exit, label %loop 363 364exit: 365 call void @llvm.objc.release(ptr %a) nounwind 366 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 367 ret void 368} 369 370define void @test10(ptr %a, i1 %arg) nounwind { 371; CHECK-LABEL: @test10( 372; CHECK-NEXT: entry: 373; CHECK-NEXT: br label [[LOOP:%.*]] 374; CHECK: loop: 375; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 376; CHECK: true: 377; CHECK-NEXT: call void @callee() 378; CHECK-NEXT: br label [[MORE]] 379; CHECK: more: 380; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 381; CHECK: exit: 382; CHECK-NEXT: ret void 383; 384entry: 385 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 386 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 387 br label %loop 388 389loop: 390 br i1 %arg, label %true, label %more 391 392true: 393 call void @callee() 394 br label %more 395 396more: 397 br i1 %arg, label %exit, label %loop 398 399exit: 400 call void @llvm.objc.release(ptr %a) nounwind 401 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 402 ret void 403} 404 405define void @test11(ptr %a, i1 %arg) nounwind { 406; CHECK-LABEL: @test11( 407; CHECK-NEXT: entry: 408; CHECK-NEXT: br label [[LOOP:%.*]] 409; CHECK: loop: 410; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 411; CHECK: true: 412; CHECK-NEXT: br label [[MORE]] 413; CHECK: more: 414; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 415; CHECK: exit: 416; CHECK-NEXT: ret void 417; 418entry: 419 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 420 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 421 br label %loop 422 423loop: 424 br i1 %arg, label %true, label %more 425 426true: 427 br label %more 428 429more: 430 br i1 %arg, label %exit, label %loop 431 432exit: 433 call void @llvm.objc.release(ptr %a) nounwind 434 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 435 ret void 436} 437 438; Don't delete anything if they're not balanced. 439 440define void @test12(ptr %a, i1 %arg) nounwind { 441; CHECK-LABEL: @test12( 442; CHECK-NEXT: entry: 443; CHECK-NEXT: [[OUTER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 444; CHECK-NEXT: [[INNER:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]] 445; CHECK-NEXT: br label [[LOOP:%.*]] 446; CHECK: loop: 447; CHECK-NEXT: br i1 %arg, label [[TRUE:%.*]], label [[MORE:%.*]] 448; CHECK: true: 449; CHECK-NEXT: ret void 450; CHECK: more: 451; CHECK-NEXT: br i1 %arg, label [[EXIT:%.*]], label [[LOOP]] 452; CHECK: exit: 453; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]] 454; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 455; CHECK-NEXT: ret void 456; 457entry: 458 %outer = tail call ptr @llvm.objc.retain(ptr %a) nounwind 459 %inner = tail call ptr @llvm.objc.retain(ptr %a) nounwind 460 br label %loop 461 462loop: 463 br i1 %arg, label %true, label %more 464 465true: 466 ret void 467 468more: 469 br i1 %arg, label %exit, label %loop 470 471exit: 472 call void @llvm.objc.release(ptr %a) nounwind 473 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 474 ret void 475} 476 477; Do not improperly pair retains in a for loop with releases outside of a for 478; loop when the proper pairing is disguised by a separate provenance represented 479; by an alloca. 480; rdar://12969722 481 482define void @test13(ptr %a, i1 %arg) nounwind { 483; CHECK-LABEL: @test13( 484; CHECK-NEXT: entry: 485; CHECK-NEXT: [[BLOCK:%.*]] = alloca ptr, align 8 486; CHECK-NEXT: [[A1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A:%.*]]) #[[ATTR0]] 487; CHECK-NEXT: br label [[LOOP:%.*]] 488; CHECK: loop: 489; CHECK-NEXT: [[A2:%.*]] = tail call ptr @llvm.objc.retain(ptr [[A]]) #[[ATTR0]] 490; CHECK-NEXT: store ptr [[A]], ptr [[BLOCK]], align 8 491; CHECK-NEXT: call void @block_callee(ptr [[BLOCK]]) 492; CHECK-NEXT: [[RELOADED_A:%.*]] = load ptr, ptr [[BLOCK]], align 8 493; CHECK-NEXT: call void @llvm.objc.release(ptr [[RELOADED_A]]) #[[ATTR0]], !clang.imprecise_release !0 494; CHECK-NEXT: br i1 %arg, label [[LOOP]], label [[EXIT:%.*]] 495; CHECK: exit: 496; CHECK-NEXT: call void @llvm.objc.release(ptr [[A]]) #[[ATTR0]], !clang.imprecise_release !0 497; CHECK-NEXT: ret void 498; 499entry: 500 %block = alloca ptr 501 %a1 = tail call ptr @llvm.objc.retain(ptr %a) nounwind 502 br label %loop 503 504loop: 505 %a2 = tail call ptr @llvm.objc.retain(ptr %a) nounwind 506 store ptr %a, ptr %block, align 8 507 call void @block_callee(ptr %block) 508 %reloaded_a = load ptr, ptr %block, align 8 509 call void @llvm.objc.release(ptr %reloaded_a) nounwind, !clang.imprecise_release !0 510 br i1 %arg, label %loop, label %exit 511 512exit: 513 call void @llvm.objc.release(ptr %a) nounwind, !clang.imprecise_release !0 514 ret void 515} 516 517; The retain call in the entry block shouldn't be moved to the loop body. 518 519define void @test14(ptr %val0, i8 %val1) { 520; CHECK-LABEL: @test14( 521; CHECK-NEXT: entry: 522; CHECK-NEXT: [[V1:%.*]] = tail call ptr @llvm.objc.retain(ptr [[VAL0:%.*]]) #[[ATTR0]] 523; CHECK-NEXT: [[CMP:%.*]] = icmp eq ptr [[VAL0]], null 524; CHECK-NEXT: br i1 [[CMP]], label [[IF_END27:%.*]], label [[IF_THEN:%.*]] 525; CHECK: if.then: 526; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i8 [[VAL1:%.*]], 1 527; CHECK-NEXT: br label [[FOR_BODY:%.*]] 528; CHECK: for.cond: 529; CHECK-NEXT: [[CMP6:%.*]] = icmp eq i8 [[VAL1]], 2 530; CHECK-NEXT: br i1 [[CMP6]], label [[FOR_BODY]], label [[FOR_END_LOOPEXIT:%.*]] 531; CHECK: for.body: 532; CHECK-NEXT: call void @callee() 533; CHECK-NEXT: [[TOBOOL9:%.*]] = icmp eq i8 [[VAL1]], 0 534; CHECK-NEXT: br i1 [[TOBOOL9]], label [[FOR_COND:%.*]], label [[IF_THEN10:%.*]] 535; CHECK: if.then10: 536; CHECK-NEXT: br label [[FOR_END:%.*]] 537; CHECK: for.end.loopexit: 538; CHECK-NEXT: br label [[FOR_END]] 539; CHECK: for.end: 540; CHECK-NEXT: call void @callee() 541; CHECK-NEXT: call void @use_pointer(ptr [[V1]]) 542; CHECK-NEXT: br label [[IF_END27]] 543; CHECK: if.end27: 544; CHECK-NEXT: call void @llvm.objc.release(ptr [[V1]]) #[[ATTR0]], !clang.imprecise_release !0 545; CHECK-NEXT: ret void 546; 547entry: 548 %v1 = tail call ptr @llvm.objc.retain(ptr %val0) 549 %cmp = icmp eq ptr %val0, null 550 br i1 %cmp, label %if.end27, label %if.then 551 552if.then: 553 %tobool = icmp eq i8 %val1, 1 554 br label %for.body 555 556for.cond: 557 %cmp6 = icmp eq i8 %val1, 2 558 br i1 %cmp6, label %for.body, label %for.end.loopexit 559 560for.body: 561 call void @callee() 562 %tobool9 = icmp eq i8 %val1, 0 563 br i1 %tobool9, label %for.cond, label %if.then10 564 565if.then10: 566 br label %for.end 567 568for.end.loopexit: 569 br label %for.end 570 571for.end: 572 call void @callee() 573 call void @use_pointer(ptr %v1) 574 br label %if.end27 575 576if.end27: 577 call void @llvm.objc.release(ptr %v1) #0, !clang.imprecise_release !0 578 ret void 579} 580 581 582!0 = !{} 583