brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.5 KiB · 24f9a71 Raw
257 lines · plain
1; RUN: opt -passes=objc-arc-contract -S < %s | FileCheck %s2 3target datalayout = "e-p:64:64:64"4 5declare ptr @llvm.objc.retain(ptr)6declare void @llvm.objc.release(ptr)7declare ptr @llvm.objc.autorelease(ptr)8declare ptr @llvm.objc.autoreleaseReturnValue(ptr)9declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)10 11declare void @use_pointer(ptr)12declare ptr @returner()13declare void @callee()14 15; CHECK-LABEL: define void @test0(16; CHECK: call void @use_pointer(ptr %0)17; CHECK: }18define void @test0(ptr %x) nounwind {19entry:20  %0 = call ptr @llvm.objc.retain(ptr %x) nounwind21  call void @use_pointer(ptr %x)22  ret void23}24 25; CHECK-LABEL: define void @test1(26; CHECK: call void @use_pointer(ptr %0)27; CHECK: }28define void @test1(ptr %x) nounwind {29entry:30  %0 = call ptr @llvm.objc.autorelease(ptr %x) nounwind31  call void @use_pointer(ptr %x)32  ret void33}34 35; Merge objc_retain and objc_autorelease into objc_retainAutorelease.36 37; CHECK-LABEL: define void @test2(38; CHECK: tail call ptr @llvm.objc.retainAutorelease(ptr %x) [[NUW:#[0-9]+]]39; CHECK: }40define void @test2(ptr %x) nounwind {41entry:42  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind43  call ptr @llvm.objc.autorelease(ptr %0) nounwind44  call void @use_pointer(ptr %x)45  ret void46}47 48; Same as test2 but the value is returned. Do an RV optimization.49 50; CHECK-LABEL: define ptr @test2b(51; CHECK: tail call ptr @llvm.objc.retainAutoreleaseReturnValue(ptr %x) [[NUW]]52; CHECK: }53define ptr @test2b(ptr %x) nounwind {54entry:55  %0 = tail call ptr @llvm.objc.retain(ptr %x) nounwind56  tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %0) nounwind57  ret ptr %x58}59 60; Merge a retain,autorelease pair around a call.61 62; CHECK-LABEL: define void @test3(63; CHECK: tail call ptr @llvm.objc.retainAutorelease(ptr %x) [[NUW]]64; CHECK: @use_pointer(ptr %0)65; CHECK: }66define void @test3(ptr %x, i64 %n) {67entry:68  tail call ptr @llvm.objc.retain(ptr %x) nounwind69  call void @use_pointer(ptr %x)70  call ptr @llvm.objc.autorelease(ptr %x) nounwind71  ret void72}73 74; Trivial retain,autorelease pair with intervening call, but it's post-dominated75; by another release. The retain and autorelease can be merged.76 77; CHECK-LABEL: define void @test4(78; CHECK-NEXT: entry:79; CHECK-NEXT: @llvm.objc.retainAutorelease(ptr %x) [[NUW]]80; CHECK-NEXT: @use_pointer81; CHECK-NEXT: @llvm.objc.release82; CHECK-NEXT: ret void83; CHECK-NEXT: }84define void @test4(ptr %x, i64 %n) {85entry:86  tail call ptr @llvm.objc.retain(ptr %x) nounwind87  call void @use_pointer(ptr %x)88  call ptr @llvm.objc.autorelease(ptr %x) nounwind89  tail call void @llvm.objc.release(ptr %x) nounwind90  ret void91}92 93; Don't merge retain and autorelease if they're not control-equivalent.94 95; CHECK-LABEL: define void @test5(96; CHECK: tail call ptr @llvm.objc.retain(ptr %p) [[NUW]]97; CHECK: true:98; CHECK: call ptr @llvm.objc.autorelease(ptr %0) [[NUW]]99; CHECK: }100define void @test5(ptr %p, i1 %a) {101entry:102  tail call ptr @llvm.objc.retain(ptr %p) nounwind103  br i1 %a, label %true, label %false104 105true:106  call ptr @llvm.objc.autorelease(ptr %p) nounwind107  call void @use_pointer(ptr %p)108  ret void109 110false:111  ret void112}113 114; Don't eliminate objc_retainAutoreleasedReturnValue by merging it into115; an objc_autorelease.116; TODO? Merge objc_retainAutoreleasedReturnValue and objc_autorelease into117; objc_retainAutoreleasedReturnValueAutorelease and merge118; objc_retainAutoreleasedReturnValue and objc_autoreleaseReturnValue119; into objc_retainAutoreleasedReturnValueAutoreleaseReturnValue?120; Those entrypoints don't exist yet though.121 122; CHECK-LABEL: define ptr @test6(123; CHECK: call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %p) [[NUW]]124; CHECK: %t = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %1) [[NUW]]125; CHECK: }126define ptr @test6() {127  %p = call ptr @returner()128  tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %p) nounwind129  %t = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %p) nounwind130  call void @use_pointer(ptr %t)131  ret ptr %t132}133 134; Don't spoil the RV optimization.135 136; CHECK: define ptr @test7(ptr %p)137; CHECK: tail call ptr @llvm.objc.retain(ptr %p)138; CHECK: call void @use_pointer(ptr %1)139; CHECK: tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %1)140; CHECK: ret ptr %2141; CHECK-NEXT: }142define ptr @test7(ptr %p) {143  %1 = tail call ptr @llvm.objc.retain(ptr %p)144  call void @use_pointer(ptr %p)145  %2 = tail call ptr @llvm.objc.autoreleaseReturnValue(ptr %p)146  ret ptr %p147}148 149; Do the return value substitution for PHI nodes too.150 151; CHECK-LABEL: define ptr @test8(152; CHECK: %retval = phi ptr [ %p, %if.then ], [ null, %entry ]153; CHECK: }154define ptr @test8(i1 %x, ptr %c) {155entry:156  br i1 %x, label %return, label %if.then157 158if.then:                                          ; preds = %entry159  %p = call ptr @llvm.objc.retain(ptr %c) nounwind160  br label %return161 162return:                                           ; preds = %if.then, %entry163  %retval = phi ptr [ %c, %if.then ], [ null, %entry ]164  ret ptr %retval165}166 167; Kill calls to @llvm.objc.clang.arc.use(...)168; CHECK-LABEL: define void @test9(169; CHECK-NOT: clang.arc.use170; CHECK: }171define void @test9(ptr %a, ptr %b) {172  call void (...) @llvm.objc.clang.arc.use(ptr %a, ptr %b) nounwind173  ret void174}175 176 177; Turn objc_retain into objc_retainAutoreleasedReturnValue if its operand178; is a return value.179 180; CHECK: define void @test10()181; CHECK: tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %p)182define void @test10() {183  %p = call ptr @returner()184  tail call ptr @llvm.objc.retain(ptr %p) nounwind185  ret void186}187 188; Convert objc_retain to objc_retainAutoreleasedReturnValue if its189; argument is a return value.190 191; CHECK-LABEL: define void @test11(192; CHECK-NEXT: %y = call ptr @returner()193; CHECK-NEXT: tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %y) [[NUW]]194; CHECK-NEXT: ret void195define void @test11() {196  %y = call ptr @returner()197  tail call ptr @llvm.objc.retain(ptr %y) nounwind198  ret void199}200 201; Don't convert objc_retain to objc_retainAutoreleasedReturnValue if its202; argument is not a return value.203 204; CHECK-LABEL: define void @test12(205; CHECK-NEXT: tail call ptr @llvm.objc.retain(ptr %y) [[NUW]]206; CHECK-NEXT: ret void207; CHECK-NEXT: }208define void @test12(ptr %y) {209  tail call ptr @llvm.objc.retain(ptr %y) nounwind210  ret void211}212 213; Don't Convert objc_retain to objc_retainAutoreleasedReturnValue if it214; isn't next to the call providing its return value.215 216; CHECK-LABEL: define void @test13(217; CHECK-NEXT: %y = call ptr @returner()218; CHECK-NEXT: call void @callee()219; CHECK-NEXT: tail call ptr @llvm.objc.retain(ptr %y) [[NUW]]220; CHECK-NEXT: ret void221; CHECK-NEXT: }222define void @test13() {223  %y = call ptr @returner()224  call void @callee()225  tail call ptr @llvm.objc.retain(ptr %y) nounwind226  ret void227}228 229; CHECK-LABEL: define void @test14(230; CHECK-NOT: clang.arc.noop.use231; CHECK: ret void232define void @test14(ptr %a, ptr %b) {233  call void (...) @llvm.objc.clang.arc.noop.use(ptr %a, ptr %b) nounwind234  ret void235}236 237define void @test15(ptr %x) {238; CHECK-LABEL: define void @test15(239; CHECK-SAME: ptr [[X:%.*]]) {240; CHECK-NEXT:    [[Y:%.*]] = getelementptr inbounds ptr, ptr [[X]], i32 0241; CHECK-NEXT:    [[V0:%.*]] = call ptr @llvm.objc.retain(ptr [[Y]]) #[[ATTR0:[0-9]+]]242; CHECK-NEXT:    call void @use_pointer(ptr [[V0]])243; CHECK-NEXT:    call void @use_pointer(ptr [[V0]])244; CHECK-NEXT:    ret void245;246  %y = getelementptr inbounds ptr, ptr %x, i32 0247  %v0 = call ptr @llvm.objc.retain(ptr %y) nounwind248  call void @use_pointer(ptr %x)249  call void @use_pointer(ptr %y)250  ret void251}252 253declare void @llvm.objc.clang.arc.use(...) nounwind254declare void @llvm.objc.clang.arc.noop.use(...) nounwind255 256; CHECK: attributes [[NUW]] = { nounwind }257