brintos

brintos / llvm-project-archived public Read only

0
0
Text · 14.5 KiB · 6fe2edf Raw
489 lines · plain
1; RUN: opt -passes=objc-arc -S < %s | FileCheck %s2 3declare ptr @llvm.objc.retain(ptr)4declare ptr @llvm.objc.retainAutoreleasedReturnValue(ptr)5declare void @llvm.objc.release(ptr)6declare ptr @llvm.objc.autorelease(ptr)7declare ptr @llvm.objc.autoreleaseReturnValue(ptr)8declare void @llvm.objc.autoreleasePoolPop(ptr)9declare ptr @llvm.objc.autoreleasePoolPush()10declare ptr @llvm.objc.retainBlock(ptr)11 12declare ptr @objc_retainedObject(ptr)13declare ptr @objc_unretainedObject(ptr)14declare ptr @objc_unretainedPointer(ptr)15 16declare void @use_pointer(ptr)17declare void @callee()18declare void @callee_fnptr(ptr)19declare void @invokee()20declare ptr @returner()21declare ptr @returner1()22declare ptr @returner2()23declare void @bar(ptr)24declare void @use_alloca(ptr)25 26declare void @llvm.dbg.value(metadata, metadata, metadata)27 28declare ptr @objc_msgSend(ptr, ptr, ...)29 30 31; In the presence of allocas, unconditionally remove retain/release pairs only32; if they are known safe in both directions. This prevents matching up an inner33; retain with the boundary guarding release in the following situation:34; 35; %A = alloca36; retain(%x)37; retain(%x) <--- Inner Retain38; store %x, %A39; %y = load %A40; ... DO STUFF ...41; release(%y)42; release(%x) <--- Guarding Release43;44; rdar://1375031945 46; CHECK: define void @test1a(ptr %x)47; CHECK: @llvm.objc.retain(ptr %x)48; CHECK: @llvm.objc.retain(ptr %x)49; CHECK: @llvm.objc.release(ptr %y)50; CHECK: @llvm.objc.release(ptr %x)51; CHECK: ret void52; CHECK: }53define void @test1a(ptr %x) {54entry:55  %A = alloca ptr56  tail call ptr @llvm.objc.retain(ptr %x)57  tail call ptr @llvm.objc.retain(ptr %x)58  store ptr %x, ptr %A, align 859  %y = load ptr, ptr %A60  call void @use_alloca(ptr %A)61  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !062  call void @use_pointer(ptr %x)63  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !064  ret void65}66 67; CHECK: define void @test1b(ptr %x)68; CHECK: @llvm.objc.retain(ptr %x)69; CHECK: @llvm.objc.retain(ptr %x)70; CHECK: @llvm.objc.release(ptr %y)71; CHECK: @llvm.objc.release(ptr %x)72; CHECK: ret void73; CHECK: }74define void @test1b(ptr %x) {75entry:76  %A = alloca ptr77  tail call ptr @llvm.objc.retain(ptr %x)78  tail call ptr @llvm.objc.retain(ptr %x)79  store ptr %x, ptr %A, align 880  %y = load ptr, ptr %A81  call void @use_alloca(ptr %A)82  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !083  call void @use_pointer(ptr %x)84  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !085  ret void86}87 88 89; CHECK: define void @test1c(ptr %x)90; CHECK: @llvm.objc.retain(ptr %x)91; CHECK: @llvm.objc.retain(ptr %x)92; CHECK: @llvm.objc.release(ptr %y)93; CHECK: @llvm.objc.release(ptr %x)94; CHECK: ret void95; CHECK: }96define void @test1c(ptr %x) {97entry:98  %A = alloca ptr, i32 399  %gep = getelementptr ptr, ptr %A, i32 2100  tail call ptr @llvm.objc.retain(ptr %x)101  tail call ptr @llvm.objc.retain(ptr %x)102  store ptr %x, ptr %gep, align 8103  %y = load ptr, ptr %gep104  call void @use_alloca(ptr %A)105  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0106  call void @use_pointer(ptr %x)107  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0108  ret void109}110 111 112; CHECK: define void @test1d(ptr %x, i1 %arg)113; CHECK: @llvm.objc.retain(ptr %x)114; CHECK: @llvm.objc.retain(ptr %x)115; CHECK: @llvm.objc.release(ptr %y)116; CHECK: @llvm.objc.release(ptr %x)117; CHECK: ret void118; CHECK: }119define void @test1d(ptr %x, i1 %arg) {120entry:121  br i1 %arg, label %use_allocaA, label %use_allocaB122 123use_allocaA:124  %allocaA = alloca ptr125  br label %exit126 127use_allocaB:128  %allocaB = alloca ptr129  br label %exit130 131exit:132  %A = phi ptr [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]133  tail call ptr @llvm.objc.retain(ptr %x)134  tail call ptr @llvm.objc.retain(ptr %x)135  store ptr %x, ptr %A, align 8136  %y = load ptr, ptr %A137  call void @use_alloca(ptr %A)138  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0139  call void @use_pointer(ptr %x)140  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0141  ret void142}143 144; CHECK: define void @test1e(ptr %x, i1 %arg)145; CHECK: @llvm.objc.retain(ptr %x)146; CHECK: @llvm.objc.retain(ptr %x)147; CHECK: @llvm.objc.release(ptr %y)148; CHECK: @llvm.objc.release(ptr %x)149; CHECK: ret void150; CHECK: }151define void @test1e(ptr %x, i1 %arg) {152entry:153  br i1 %arg, label %use_allocaA, label %use_allocaB154 155use_allocaA:156  %allocaA = alloca ptr, i32 4157  br label %exit158 159use_allocaB:160  %allocaB = alloca ptr, i32 4161  br label %exit162 163exit:164  %A = phi ptr [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]165  %gep = getelementptr ptr, ptr %A, i32 2166  tail call ptr @llvm.objc.retain(ptr %x)167  tail call ptr @llvm.objc.retain(ptr %x)168  store ptr %x, ptr %gep, align 8169  %y = load ptr, ptr %gep170  call void @use_alloca(ptr %A)171  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0172  call void @use_pointer(ptr %x)173  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0174  ret void175}176 177; CHECK: define void @test1f(ptr %x)178; CHECK: @llvm.objc.retain(ptr %x)179; CHECK: @llvm.objc.retain(ptr %x)180; CHECK: @llvm.objc.release(ptr %y)181; CHECK: @llvm.objc.release(ptr %x)182; CHECK: ret void183; CHECK: }184define void @test1f(ptr %x) {185entry:186  %allocaOne = alloca ptr187  %allocaTwo = alloca ptr188  %A = select i1 undef, ptr %allocaOne, ptr %allocaTwo189  tail call ptr @llvm.objc.retain(ptr %x)190  tail call ptr @llvm.objc.retain(ptr %x)191  store ptr %x, ptr %A, align 8192  %y = load ptr, ptr %A193  call void @use_alloca(ptr %A)194  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0195  call void @use_pointer(ptr %x)196  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0197  ret void198}199 200; Make sure that if a store is in a different basic block we handle known safe201; conservatively.202 203 204; CHECK: define void @test2a(ptr %x)205; CHECK: @llvm.objc.retain(ptr %x)206; CHECK: @llvm.objc.retain(ptr %x)207; CHECK: @llvm.objc.release(ptr %y)208; CHECK: @llvm.objc.release(ptr %x)209; CHECK: ret void210; CHECK: }211define void @test2a(ptr %x) {212entry:213  %A = alloca ptr214  store ptr %x, ptr %A, align 8215  %y = load ptr, ptr %A216  br label %bb1217 218bb1:219  br label %bb2220 221bb2:222  br label %bb3223 224bb3:225  tail call ptr @llvm.objc.retain(ptr %x)226  tail call ptr @llvm.objc.retain(ptr %x)227  call void @use_alloca(ptr %A)228  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0229  call void @use_pointer(ptr %x)230  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0231  ret void232}233 234; CHECK: define void @test2b(ptr %x)235; CHECK: @llvm.objc.retain(ptr %x)236; CHECK: @llvm.objc.retain(ptr %x)237; CHECK: @llvm.objc.release(ptr %y)238; CHECK: @llvm.objc.release(ptr %x)239; CHECK: ret void240; CHECK: }241define void @test2b(ptr %x) {242entry:243  %A = alloca ptr244  store ptr %x, ptr %A, align 8245  %y = load ptr, ptr %A246  br label %bb1247 248bb1:249  br label %bb2250 251bb2:252  br label %bb3253 254bb3:255  tail call ptr @llvm.objc.retain(ptr %x)256  tail call ptr @llvm.objc.retain(ptr %x)257  call void @use_alloca(ptr %A)258  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0259  call void @use_pointer(ptr %x)260  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0261  ret void262}263 264; CHECK: define void @test2c(ptr %x)265; CHECK: @llvm.objc.retain(ptr %x)266; CHECK: @llvm.objc.retain(ptr %x)267; CHECK: @llvm.objc.release(ptr %y)268; CHECK: @llvm.objc.release(ptr %x)269; CHECK: ret void270; CHECK: }271define void @test2c(ptr %x) {272entry:273  %A = alloca ptr, i32 3274  %gep1 = getelementptr ptr, ptr %A, i32 2275  store ptr %x, ptr %gep1, align 8276  %gep2 = getelementptr ptr, ptr %A, i32 2277  %y = load ptr, ptr %gep2278  tail call ptr @llvm.objc.retain(ptr %x)279  br label %bb1280 281bb1:282  br label %bb2283 284bb2:285  br label %bb3286 287bb3:288  tail call ptr @llvm.objc.retain(ptr %x)289  call void @use_alloca(ptr %A)290  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0291  call void @use_pointer(ptr %x)292  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0293  ret void294}295 296; CHECK: define void @test2d(ptr %x)297; CHECK: @llvm.objc.retain(ptr %x)298; CHECK: @llvm.objc.retain(ptr %x)299; CHECK: @llvm.objc.release(ptr %y)300; CHECK: @llvm.objc.release(ptr %x)301; CHECK: ret void302; CHECK: }303define void @test2d(ptr %x) {304entry:305  tail call ptr @llvm.objc.retain(ptr %x)306  br label %bb1307 308bb1:309  %Abb1 = alloca ptr, i32 3310  %gepbb11 = getelementptr ptr, ptr %Abb1, i32 2311  store ptr %x, ptr %gepbb11, align 8312  %gepbb12 = getelementptr ptr, ptr %Abb1, i32 2313  %ybb1 = load ptr, ptr %gepbb12314  br label %bb3315 316bb2:317  %Abb2 = alloca ptr, i32 4318  %gepbb21 = getelementptr ptr, ptr %Abb2, i32 2319  store ptr %x, ptr %gepbb21, align 8320  %gepbb22 = getelementptr ptr, ptr %Abb2, i32 2321  %ybb2 = load ptr, ptr %gepbb22322  br label %bb3323 324bb3:325  %A = phi ptr [ %Abb1, %bb1 ], [ %Abb2, %bb2 ]326  %y = phi ptr [ %ybb1, %bb1 ], [ %ybb2, %bb2 ]327  tail call ptr @llvm.objc.retain(ptr %x)328  call void @use_alloca(ptr %A)329  call void @llvm.objc.release(ptr %y), !clang.imprecise_release !0330  call void @use_pointer(ptr %x)331  call void @llvm.objc.release(ptr %x), !clang.imprecise_release !0332  ret void333}334 335; Make sure in the presence of allocas, if we find a cfghazard we do not perform336; code motion even if we are known safe. These two concepts are separate and337; should be treated as such.338;339; rdar://13949644340 341; CHECK: define void @test3a() {342; CHECK: entry:343; CHECK:   @llvm.objc.retainAutoreleasedReturnValue344; CHECK:   @llvm.objc.retain345; CHECK:   @llvm.objc.retain346; CHECK:   @llvm.objc.retain347; CHECK:   @llvm.objc.retain348; CHECK: arraydestroy.body:349; CHECK:   @llvm.objc.release350; CHECK-NOT: @llvm.objc.release351; CHECK: arraydestroy.done:352; CHECK-NOT: @llvm.objc.release353; CHECK: arraydestroy.body1:354; CHECK:   @llvm.objc.release355; CHECK-NOT: @llvm.objc.release356; CHECK: arraydestroy.done1:357; CHECK: @llvm.objc.release358; CHECK: ret void359; CHECK: }360define void @test3a() {361entry:362  %keys = alloca [2 x ptr], align 16363  %objs = alloca [2 x ptr], align 16364  365  %call1 = call ptr @returner()366  %tmp0 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1)367 368  tail call ptr @llvm.objc.retain(ptr %call1)369  store ptr %call1, ptr %objs, align 8370  %objs.elt = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 1371  tail call ptr @llvm.objc.retain(ptr %call1)372  store ptr %call1, ptr %objs.elt373 374  %call2 = call ptr @returner1()375  %call3 = call ptr @returner2()376  tail call ptr @llvm.objc.retain(ptr %call2)377  store ptr %call2, ptr %keys, align 8378  %keys.elt = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 1379  tail call ptr @llvm.objc.retain(ptr %call3)380  store ptr %call3, ptr %keys.elt  381  382  %gep = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 2383  br label %arraydestroy.body384 385arraydestroy.body:386  %arraydestroy.elementPast = phi ptr [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]387  %arraydestroy.element = getelementptr inbounds ptr, ptr %arraydestroy.elementPast, i64 -1388  %destroy_tmp = load ptr, ptr %arraydestroy.element, align 8389  call void @llvm.objc.release(ptr %destroy_tmp), !clang.imprecise_release !0390  %arraydestroy.cmp = icmp eq ptr %arraydestroy.element, %objs391  br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body392 393arraydestroy.done:394  %gep1 = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 2395  br label %arraydestroy.body1396 397arraydestroy.body1:398  %arraydestroy.elementPast1 = phi ptr [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]399  %arraydestroy.element1 = getelementptr inbounds ptr, ptr %arraydestroy.elementPast1, i64 -1400  %destroy_tmp1 = load ptr, ptr %arraydestroy.element1, align 8401  call void @llvm.objc.release(ptr %destroy_tmp1), !clang.imprecise_release !0402  %arraydestroy.cmp1 = icmp eq ptr %arraydestroy.element1, %keys403  br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1404 405arraydestroy.done1:406  call void @llvm.objc.release(ptr %call1), !clang.imprecise_release !0407  ret void408}409 410; Make sure that even though we stop said code motion we still allow for411; pointers to be removed if we are known safe in both directions.412;413; rdar://13949644414 415; CHECK: define void @test3b() {416; CHECK: entry:417; CHECK:   @llvm.objc.retainAutoreleasedReturnValue418; CHECK:   @llvm.objc.retain419; CHECK:   @llvm.objc.retain420; CHECK:   @llvm.objc.retain421; CHECK:   @llvm.objc.retain422; CHECK: arraydestroy.body:423; CHECK:   @llvm.objc.release424; CHECK-NOT: @llvm.objc.release425; CHECK: arraydestroy.done:426; CHECK-NOT: @llvm.objc.release427; CHECK: arraydestroy.body1:428; CHECK:   @llvm.objc.release429; CHECK-NOT: @llvm.objc.release430; CHECK: arraydestroy.done1:431; CHECK: @llvm.objc.release432; CHECK: ret void433; CHECK: }434define void @test3b() {435entry:436  %keys = alloca [2 x ptr], align 16437  %objs = alloca [2 x ptr], align 16438  439  %call1 = call ptr @returner()440  %tmp0 = tail call ptr @llvm.objc.retainAutoreleasedReturnValue(ptr %call1)441  %tmp1 = tail call ptr @llvm.objc.retain(ptr %call1)442 443  tail call ptr @llvm.objc.retain(ptr %call1)444  store ptr %call1, ptr %objs, align 8445  %objs.elt = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 1446  tail call ptr @llvm.objc.retain(ptr %call1)447  store ptr %call1, ptr %objs.elt448 449  %call2 = call ptr @returner1()450  %call3 = call ptr @returner2()451  tail call ptr @llvm.objc.retain(ptr %call2)452  store ptr %call2, ptr %keys, align 8453  %keys.elt = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 1454  tail call ptr @llvm.objc.retain(ptr %call3)455  store ptr %call3, ptr %keys.elt  456  457  %gep = getelementptr inbounds [2 x ptr], ptr %objs, i64 0, i64 2458  br label %arraydestroy.body459 460arraydestroy.body:461  %arraydestroy.elementPast = phi ptr [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]462  %arraydestroy.element = getelementptr inbounds ptr, ptr %arraydestroy.elementPast, i64 -1463  %destroy_tmp = load ptr, ptr %arraydestroy.element, align 8464  call void @llvm.objc.release(ptr %destroy_tmp), !clang.imprecise_release !0465  %arraydestroy.cmp = icmp eq ptr %arraydestroy.element, %objs466  br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body467 468arraydestroy.done:469  %gep1 = getelementptr inbounds [2 x ptr], ptr %keys, i64 0, i64 2470  br label %arraydestroy.body1471 472arraydestroy.body1:473  %arraydestroy.elementPast1 = phi ptr [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]474  %arraydestroy.element1 = getelementptr inbounds ptr, ptr %arraydestroy.elementPast1, i64 -1475  %destroy_tmp1 = load ptr, ptr %arraydestroy.element1, align 8476  call void @llvm.objc.release(ptr %destroy_tmp1), !clang.imprecise_release !0477  %arraydestroy.cmp1 = icmp eq ptr %arraydestroy.element1, %keys478  br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1479 480arraydestroy.done1:481  call void @llvm.objc.release(ptr %call1), !clang.imprecise_release !0482  call void @llvm.objc.release(ptr %call1), !clang.imprecise_release !0483  ret void484}485 486!0 = !{}487 488declare i32 @__gxx_personality_v0(...)489