225 lines · plain
1; RUN: opt -S -passes=objc-arc < %s | FileCheck %s2 3declare ptr @llvm.objc.retain(ptr)4declare void @llvm.objc.release(ptr)5declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)6declare ptr @objc_msgSend(ptr, ptr, ...)7declare void @use_pointer(ptr)8declare void @callee()9declare ptr @returner()10 11; ARCOpt shouldn't try to move the releases to the block containing the invoke.12 13; CHECK-LABEL: define void @test0(14; CHECK: invoke.cont:15; CHECK: call void @llvm.objc.release(ptr %zipFile) [[NUW:#[0-9]+]], !clang.imprecise_release !016; CHECK: ret void17; CHECK: lpad:18; CHECK: call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !019; CHECK: ret void20; CHECK-NEXT: }21define void @test0(ptr %zipFile) personality ptr @__gxx_personality_v0 {22entry:23 call ptr @llvm.objc.retain(ptr %zipFile) nounwind24 call void @use_pointer(ptr %zipFile)25 invoke void @objc_msgSend(ptr %zipFile) 26 to label %invoke.cont unwind label %lpad27 28invoke.cont: ; preds = %entry29 call void @llvm.objc.release(ptr %zipFile) nounwind, !clang.imprecise_release !030 ret void31 32lpad: ; preds = %entry33 %exn = landingpad {ptr, i32}34 cleanup35 call void @llvm.objc.release(ptr %zipFile) nounwind, !clang.imprecise_release !036 ret void37}38 39; ARCOpt should move the release before the callee calls.40 41; CHECK-LABEL: define void @test1(42; CHECK: invoke.cont:43; CHECK: call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !044; CHECK: call void @callee()45; CHECK: br label %done46; CHECK: lpad:47; CHECK: call void @llvm.objc.release(ptr %zipFile) [[NUW]], !clang.imprecise_release !048; CHECK: call void @callee()49; CHECK: br label %done50; CHECK: done:51; CHECK-NEXT: ret void52; CHECK-NEXT: }53define void @test1(ptr %zipFile) personality ptr @__gxx_personality_v0 {54entry:55 call ptr @llvm.objc.retain(ptr %zipFile) nounwind56 call void @use_pointer(ptr %zipFile)57 invoke void @objc_msgSend(ptr %zipFile)58 to label %invoke.cont unwind label %lpad59 60invoke.cont: ; preds = %entry61 call void @callee()62 br label %done63 64lpad: ; preds = %entry65 %exn = landingpad {ptr, i32}66 cleanup67 call void @callee()68 br label %done69 70done:71 call void @llvm.objc.release(ptr %zipFile) nounwind, !clang.imprecise_release !072 ret void73}74 75; The optimizer should ignore invoke unwind paths consistently.76; PR1226577 78; CHECK: define void @test2() personality ptr @__objc_personality_v0 {79; CHECK: invoke.cont:80; CHECK-NEXT: call ptr @llvm.objc.retain81; CHECK-NOT: @llvm.objc.r82; CHECK: finally.cont:83; CHECK-NEXT: call void @llvm.objc.release84; CHECK-NOT: @objc85; CHECK: finally.rethrow:86; CHECK-NOT: @objc87; CHECK: }88define void @test2() personality ptr @__objc_personality_v0 {89entry:90 %call = invoke ptr @objc_msgSend()91 to label %invoke.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !092 93invoke.cont: ; preds = %entry94 %tmp1 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call) nounwind95 call void @objc_msgSend(), !clang.arc.no_objc_arc_exceptions !096 invoke void @use_pointer(ptr %call)97 to label %finally.cont unwind label %finally.rethrow, !clang.arc.no_objc_arc_exceptions !098 99finally.cont: ; preds = %invoke.cont100 tail call void @llvm.objc.release(ptr %call) nounwind, !clang.imprecise_release !0101 ret void102 103finally.rethrow: ; preds = %invoke.cont, %entry104 %tmp2 = landingpad { ptr, i32 }105 catch ptr null106 unreachable107}108 109; Don't try to place code on invoke critical edges.110 111; CHECK-LABEL: define void @test3(112; CHECK: if.end:113; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]114; CHECK-NEXT: ret void115; CHECK-NEXT: }116define void @test3(ptr %p, i1 %b) personality ptr @__objc_personality_v0 {117entry:118 %0 = call ptr @llvm.objc.retain(ptr %p)119 call void @callee()120 br i1 %b, label %if.else, label %if.then121 122if.then:123 invoke void @use_pointer(ptr %p)124 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0125 126if.else:127 invoke void @use_pointer(ptr %p)128 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0129 130lpad:131 %r = landingpad { ptr, i32 }132 cleanup133 ret void134 135if.end:136 call void @llvm.objc.release(ptr %p)137 ret void138}139 140; Like test3, but with ARC-relevant exception handling.141 142; CHECK-LABEL: define void @test4(143; CHECK: lpad:144; CHECK-NEXT: %r = landingpad { ptr, i32 }145; CHECK-NEXT: cleanup146; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]147; CHECK-NEXT: ret void148; CHECK: if.end:149; CHECK-NEXT: call void @llvm.objc.release(ptr %p) [[NUW]]150; CHECK-NEXT: ret void151; CHECK-NEXT: }152define void @test4(ptr %p, i1 %b) personality ptr @__objc_personality_v0 {153entry:154 %0 = call ptr @llvm.objc.retain(ptr %p)155 call void @callee()156 br i1 %b, label %if.else, label %if.then157 158if.then:159 invoke void @use_pointer(ptr %p)160 to label %if.end unwind label %lpad161 162if.else:163 invoke void @use_pointer(ptr %p)164 to label %if.end unwind label %lpad165 166lpad:167 %r = landingpad { ptr, i32 }168 cleanup169 call void @llvm.objc.release(ptr %p)170 ret void171 172if.end:173 call void @llvm.objc.release(ptr %p)174 ret void175}176 177; Don't turn the retainAutoreleaseReturnValue into retain, because it's178; for an invoke which we can assume codegen will put immediately prior.179 180; CHECK-LABEL: define void @test5(181; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %z)182; CHECK: }183define void @test5() personality ptr @__objc_personality_v0 {184entry:185 %z = invoke ptr @returner()186 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0187 188lpad:189 %r13 = landingpad { ptr, i32 }190 cleanup191 ret void192 193if.end:194 call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %z)195 ret void196}197 198; Like test5, but there's intervening code.199 200; CHECK-LABEL: define void @test6(201; CHECK: call ptr @llvm.objc.retain(ptr %z)202; CHECK: }203define void @test6() personality ptr @__objc_personality_v0 {204entry:205 %z = invoke ptr @returner()206 to label %if.end unwind label %lpad, !clang.arc.no_objc_arc_exceptions !0207 208lpad:209 %r13 = landingpad { ptr, i32 }210 cleanup211 ret void212 213if.end:214 call void @callee()215 call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %z)216 ret void217}218 219declare i32 @__gxx_personality_v0(...)220declare i32 @__objc_personality_v0(...)221 222; CHECK: attributes [[NUW]] = { nounwind }223 224!0 = !{}225