Home | History | Annotate | Download | only in ObjCARC
      1 ; RUN: opt -objc-arc -S < %s | FileCheck %s
      2 
      3 declare i8* @objc_retain(i8*)
      4 declare i8* @objc_retainAutoreleasedReturnValue(i8*)
      5 declare void @objc_release(i8*)
      6 declare i8* @objc_autorelease(i8*)
      7 declare i8* @objc_autoreleaseReturnValue(i8*)
      8 declare void @objc_autoreleasePoolPop(i8*)
      9 declare i8* @objc_autoreleasePoolPush()
     10 declare i8* @objc_retainBlock(i8*)
     11 
     12 declare i8* @objc_retainedObject(i8*)
     13 declare i8* @objc_unretainedObject(i8*)
     14 declare i8* @objc_unretainedPointer(i8*)
     15 
     16 declare void @use_pointer(i8*)
     17 declare void @callee()
     18 declare void @callee_fnptr(void ()*)
     19 declare void @invokee()
     20 declare i8* @returner()
     21 declare i8* @returner1()
     22 declare i8* @returner2()
     23 declare void @bar(i32 ()*)
     24 declare void @use_alloca(i8**)
     25 
     26 declare void @llvm.dbg.value(metadata, i64, metadata)
     27 
     28 declare i8* @objc_msgSend(i8*, i8*, ...)
     29 
     30 
     31 ; In the presence of allocas, unconditionally remove retain/release pairs only
     32 ; if they are known safe in both directions. This prevents matching up an inner
     33 ; retain with the boundary guarding release in the following situation:
     34 ; 
     35 ; %A = alloca
     36 ; retain(%x)
     37 ; retain(%x) <--- Inner Retain
     38 ; store %x, %A
     39 ; %y = load %A
     40 ; ... DO STUFF ...
     41 ; release(%y)
     42 ; release(%x) <--- Guarding Release
     43 ;
     44 ; rdar://13750319
     45 
     46 ; CHECK: define void @test1a(i8* %x)
     47 ; CHECK: @objc_retain(i8* %x)
     48 ; CHECK: @objc_retain(i8* %x)
     49 ; CHECK: @objc_release(i8* %y)
     50 ; CHECK: @objc_release(i8* %x)
     51 ; CHECK: ret void
     52 ; CHECK: }
     53 define void @test1a(i8* %x) {
     54 entry:
     55   %A = alloca i8*
     56   tail call i8* @objc_retain(i8* %x)
     57   tail call i8* @objc_retain(i8* %x)
     58   store i8* %x, i8** %A, align 8
     59   %y = load i8** %A
     60   call void @use_alloca(i8** %A)
     61   call void @objc_release(i8* %y), !clang.imprecise_release !0
     62   call void @use_pointer(i8* %x)
     63   call void @objc_release(i8* %x), !clang.imprecise_release !0
     64   ret void
     65 }
     66 
     67 ; CHECK: define void @test1b(i8* %x)
     68 ; CHECK: @objc_retain(i8* %x)
     69 ; CHECK: @objc_retain(i8* %x)
     70 ; CHECK: @objc_release(i8* %y)
     71 ; CHECK: @objc_release(i8* %x)
     72 ; CHECK: ret void
     73 ; CHECK: }
     74 define void @test1b(i8* %x) {
     75 entry:
     76   %A = alloca i8*
     77   %gep = getelementptr i8** %A, i32 0
     78   tail call i8* @objc_retain(i8* %x)
     79   tail call i8* @objc_retain(i8* %x)
     80   store i8* %x, i8** %gep, align 8
     81   %y = load i8** %A
     82   call void @use_alloca(i8** %A)
     83   call void @objc_release(i8* %y), !clang.imprecise_release !0
     84   call void @use_pointer(i8* %x)
     85   call void @objc_release(i8* %x), !clang.imprecise_release !0
     86   ret void
     87 }
     88 
     89 
     90 ; CHECK: define void @test1c(i8* %x)
     91 ; CHECK: @objc_retain(i8* %x)
     92 ; CHECK: @objc_retain(i8* %x)
     93 ; CHECK: @objc_release(i8* %y)
     94 ; CHECK: @objc_release(i8* %x)
     95 ; CHECK: ret void
     96 ; CHECK: }
     97 define void @test1c(i8* %x) {
     98 entry:
     99   %A = alloca i8*, i32 3
    100   %gep = getelementptr i8** %A, i32 2
    101   tail call i8* @objc_retain(i8* %x)
    102   tail call i8* @objc_retain(i8* %x)
    103   store i8* %x, i8** %gep, align 8
    104   %y = load i8** %gep
    105   call void @use_alloca(i8** %A)
    106   call void @objc_release(i8* %y), !clang.imprecise_release !0
    107   call void @use_pointer(i8* %x)
    108   call void @objc_release(i8* %x), !clang.imprecise_release !0
    109   ret void
    110 }
    111 
    112 
    113 ; CHECK: define void @test1d(i8* %x)
    114 ; CHECK: @objc_retain(i8* %x)
    115 ; CHECK: @objc_retain(i8* %x)
    116 ; CHECK: @objc_release(i8* %y)
    117 ; CHECK: @objc_release(i8* %x)
    118 ; CHECK: ret void
    119 ; CHECK: }
    120 define void @test1d(i8* %x) {
    121 entry:
    122   br i1 undef, label %use_allocaA, label %use_allocaB
    123 
    124 use_allocaA:
    125   %allocaA = alloca i8*
    126   br label %exit
    127 
    128 use_allocaB:
    129   %allocaB = alloca i8*
    130   br label %exit
    131 
    132 exit:
    133   %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
    134   %gep = getelementptr i8** %A, i32 0
    135   tail call i8* @objc_retain(i8* %x)
    136   tail call i8* @objc_retain(i8* %x)
    137   store i8* %x, i8** %gep, align 8
    138   %y = load i8** %gep
    139   call void @use_alloca(i8** %A)
    140   call void @objc_release(i8* %y), !clang.imprecise_release !0
    141   call void @use_pointer(i8* %x)
    142   call void @objc_release(i8* %x), !clang.imprecise_release !0
    143   ret void
    144 }
    145 
    146 ; CHECK: define void @test1e(i8* %x)
    147 ; CHECK: @objc_retain(i8* %x)
    148 ; CHECK: @objc_retain(i8* %x)
    149 ; CHECK: @objc_release(i8* %y)
    150 ; CHECK: @objc_release(i8* %x)
    151 ; CHECK: ret void
    152 ; CHECK: }
    153 define void @test1e(i8* %x) {
    154 entry:
    155   br i1 undef, label %use_allocaA, label %use_allocaB
    156 
    157 use_allocaA:
    158   %allocaA = alloca i8*, i32 4
    159   br label %exit
    160 
    161 use_allocaB:
    162   %allocaB = alloca i8*, i32 4
    163   br label %exit
    164 
    165 exit:
    166   %A = phi i8** [ %allocaA, %use_allocaA ], [ %allocaB, %use_allocaB ]
    167   %gep = getelementptr i8** %A, i32 2
    168   tail call i8* @objc_retain(i8* %x)
    169   tail call i8* @objc_retain(i8* %x)
    170   store i8* %x, i8** %gep, align 8
    171   %y = load i8** %gep
    172   call void @use_alloca(i8** %A)
    173   call void @objc_release(i8* %y), !clang.imprecise_release !0
    174   call void @use_pointer(i8* %x)
    175   call void @objc_release(i8* %x), !clang.imprecise_release !0
    176   ret void
    177 }
    178 
    179 ; CHECK: define void @test1f(i8* %x)
    180 ; CHECK: @objc_retain(i8* %x)
    181 ; CHECK: @objc_retain(i8* %x)
    182 ; CHECK: @objc_release(i8* %y)
    183 ; CHECK: @objc_release(i8* %x)
    184 ; CHECK: ret void
    185 ; CHECK: }
    186 define void @test1f(i8* %x) {
    187 entry:
    188   %allocaOne = alloca i8*
    189   %allocaTwo = alloca i8*
    190   %A = select i1 undef, i8** %allocaOne, i8** %allocaTwo
    191   tail call i8* @objc_retain(i8* %x)
    192   tail call i8* @objc_retain(i8* %x)
    193   store i8* %x, i8** %A, align 8
    194   %y = load i8** %A
    195   call void @use_alloca(i8** %A)
    196   call void @objc_release(i8* %y), !clang.imprecise_release !0
    197   call void @use_pointer(i8* %x)
    198   call void @objc_release(i8* %x), !clang.imprecise_release !0
    199   ret void
    200 }
    201 
    202 ; Make sure that if a store is in a different basic block we handle known safe
    203 ; conservatively.
    204 
    205 
    206 ; CHECK: define void @test2a(i8* %x)
    207 ; CHECK: @objc_retain(i8* %x)
    208 ; CHECK: @objc_retain(i8* %x)
    209 ; CHECK: @objc_release(i8* %y)
    210 ; CHECK: @objc_release(i8* %x)
    211 ; CHECK: ret void
    212 ; CHECK: }
    213 define void @test2a(i8* %x) {
    214 entry:
    215   %A = alloca i8*
    216   store i8* %x, i8** %A, align 8
    217   %y = load i8** %A
    218   br label %bb1
    219 
    220 bb1:
    221   br label %bb2
    222 
    223 bb2:
    224   br label %bb3
    225 
    226 bb3:
    227   tail call i8* @objc_retain(i8* %x)
    228   tail call i8* @objc_retain(i8* %x)
    229   call void @use_alloca(i8** %A)
    230   call void @objc_release(i8* %y), !clang.imprecise_release !0
    231   call void @use_pointer(i8* %x)
    232   call void @objc_release(i8* %x), !clang.imprecise_release !0
    233   ret void
    234 }
    235 
    236 ; CHECK: define void @test2b(i8* %x)
    237 ; CHECK: @objc_retain(i8* %x)
    238 ; CHECK: @objc_retain(i8* %x)
    239 ; CHECK: @objc_release(i8* %y)
    240 ; CHECK: @objc_release(i8* %x)
    241 ; CHECK: ret void
    242 ; CHECK: }
    243 define void @test2b(i8* %x) {
    244 entry:
    245   %A = alloca i8*
    246   %gep1 = getelementptr i8** %A, i32 0
    247   store i8* %x, i8** %gep1, align 8
    248   %gep2 = getelementptr i8** %A, i32 0
    249   %y = load i8** %gep2
    250   br label %bb1
    251 
    252 bb1:
    253   br label %bb2
    254 
    255 bb2:
    256   br label %bb3
    257 
    258 bb3:
    259   tail call i8* @objc_retain(i8* %x)
    260   tail call i8* @objc_retain(i8* %x)
    261   call void @use_alloca(i8** %A)
    262   call void @objc_release(i8* %y), !clang.imprecise_release !0
    263   call void @use_pointer(i8* %x)
    264   call void @objc_release(i8* %x), !clang.imprecise_release !0
    265   ret void
    266 }
    267 
    268 ; CHECK: define void @test2c(i8* %x)
    269 ; CHECK: @objc_retain(i8* %x)
    270 ; CHECK: @objc_retain(i8* %x)
    271 ; CHECK: @objc_release(i8* %y)
    272 ; CHECK: @objc_release(i8* %x)
    273 ; CHECK: ret void
    274 ; CHECK: }
    275 define void @test2c(i8* %x) {
    276 entry:
    277   %A = alloca i8*, i32 3
    278   %gep1 = getelementptr i8** %A, i32 2
    279   store i8* %x, i8** %gep1, align 8
    280   %gep2 = getelementptr i8** %A, i32 2
    281   %y = load i8** %gep2
    282   tail call i8* @objc_retain(i8* %x)
    283   br label %bb1
    284 
    285 bb1:
    286   br label %bb2
    287 
    288 bb2:
    289   br label %bb3
    290 
    291 bb3:
    292   tail call i8* @objc_retain(i8* %x)
    293   call void @use_alloca(i8** %A)
    294   call void @objc_release(i8* %y), !clang.imprecise_release !0
    295   call void @use_pointer(i8* %x)
    296   call void @objc_release(i8* %x), !clang.imprecise_release !0
    297   ret void
    298 }
    299 
    300 ; CHECK: define void @test2d(i8* %x)
    301 ; CHECK: @objc_retain(i8* %x)
    302 ; CHECK: @objc_retain(i8* %x)
    303 ; CHECK: @objc_release(i8* %y)
    304 ; CHECK: @objc_release(i8* %x)
    305 ; CHECK: ret void
    306 ; CHECK: }
    307 define void @test2d(i8* %x) {
    308 entry:
    309   tail call i8* @objc_retain(i8* %x)
    310   br label %bb1
    311 
    312 bb1:
    313   %Abb1 = alloca i8*, i32 3
    314   %gepbb11 = getelementptr i8** %Abb1, i32 2
    315   store i8* %x, i8** %gepbb11, align 8
    316   %gepbb12 = getelementptr i8** %Abb1, i32 2
    317   %ybb1 = load i8** %gepbb12
    318   br label %bb3
    319 
    320 bb2:
    321   %Abb2 = alloca i8*, i32 4
    322   %gepbb21 = getelementptr i8** %Abb2, i32 2
    323   store i8* %x, i8** %gepbb21, align 8
    324   %gepbb22 = getelementptr i8** %Abb2, i32 2
    325   %ybb2 = load i8** %gepbb22
    326   br label %bb3
    327 
    328 bb3:
    329   %A = phi i8** [ %Abb1, %bb1 ], [ %Abb2, %bb2 ]
    330   %y = phi i8* [ %ybb1, %bb1 ], [ %ybb2, %bb2 ]
    331   tail call i8* @objc_retain(i8* %x)
    332   call void @use_alloca(i8** %A)
    333   call void @objc_release(i8* %y), !clang.imprecise_release !0
    334   call void @use_pointer(i8* %x)
    335   call void @objc_release(i8* %x), !clang.imprecise_release !0
    336   ret void
    337 }
    338 
    339 ; Make sure in the presence of allocas, if we find a cfghazard we do not perform
    340 ; code motion even if we are known safe. These two concepts are separate and
    341 ; should be treated as such.
    342 ;
    343 ; rdar://13949644
    344 
    345 ; CHECK: define void @test3a() {
    346 ; CHECK: entry:
    347 ; CHECK:   @objc_retainAutoreleasedReturnValue
    348 ; CHECK:   @objc_retain
    349 ; CHECK:   @objc_retain
    350 ; CHECK:   @objc_retain
    351 ; CHECK:   @objc_retain
    352 ; CHECK: arraydestroy.body:
    353 ; CHECK:   @objc_release
    354 ; CHECK-NOT: @objc_release
    355 ; CHECK: arraydestroy.done:
    356 ; CHECK-NOT: @objc_release
    357 ; CHECK: arraydestroy.body1:
    358 ; CHECK:   @objc_release
    359 ; CHECK-NOT: @objc_release
    360 ; CHECK: arraydestroy.done1:
    361 ; CHECK: @objc_release
    362 ; CHECK: ret void
    363 ; CHECK: }
    364 define void @test3a() {
    365 entry:
    366   %keys = alloca [2 x i8*], align 16
    367   %objs = alloca [2 x i8*], align 16
    368   
    369   %call1 = call i8* @returner()
    370   %tmp0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call1)
    371 
    372   %objs.begin = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
    373   tail call i8* @objc_retain(i8* %call1)
    374   store i8* %call1, i8** %objs.begin, align 8
    375   %objs.elt = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 1
    376   tail call i8* @objc_retain(i8* %call1)
    377   store i8* %call1, i8** %objs.elt
    378 
    379   %call2 = call i8* @returner1()
    380   %call3 = call i8* @returner2()
    381   %keys.begin = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
    382   tail call i8* @objc_retain(i8* %call2)
    383   store i8* %call2, i8** %keys.begin, align 8
    384   %keys.elt = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 1
    385   tail call i8* @objc_retain(i8* %call3)
    386   store i8* %call3, i8** %keys.elt  
    387   
    388   %gep = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 2
    389   br label %arraydestroy.body
    390 
    391 arraydestroy.body:
    392   %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
    393   %arraydestroy.element = getelementptr inbounds i8** %arraydestroy.elementPast, i64 -1
    394   %destroy_tmp = load i8** %arraydestroy.element, align 8
    395   call void @objc_release(i8* %destroy_tmp), !clang.imprecise_release !0
    396   %objs_ptr = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
    397   %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
    398   br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
    399 
    400 arraydestroy.done:
    401   %gep1 = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 2
    402   br label %arraydestroy.body1
    403 
    404 arraydestroy.body1:
    405   %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
    406   %arraydestroy.element1 = getelementptr inbounds i8** %arraydestroy.elementPast1, i64 -1
    407   %destroy_tmp1 = load i8** %arraydestroy.element1, align 8
    408   call void @objc_release(i8* %destroy_tmp1), !clang.imprecise_release !0
    409   %keys_ptr = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
    410   %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
    411   br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
    412 
    413 arraydestroy.done1:
    414   call void @objc_release(i8* %call1), !clang.imprecise_release !0
    415   ret void
    416 }
    417 
    418 ; Make sure that even though we stop said code motion we still allow for
    419 ; pointers to be removed if we are known safe in both directions.
    420 ;
    421 ; rdar://13949644
    422 
    423 ; CHECK: define void @test3b() {
    424 ; CHECK: entry:
    425 ; CHECK:   @objc_retainAutoreleasedReturnValue
    426 ; CHECK:   @objc_retain
    427 ; CHECK:   @objc_retain
    428 ; CHECK:   @objc_retain
    429 ; CHECK:   @objc_retain
    430 ; CHECK: arraydestroy.body:
    431 ; CHECK:   @objc_release
    432 ; CHECK-NOT: @objc_release
    433 ; CHECK: arraydestroy.done:
    434 ; CHECK-NOT: @objc_release
    435 ; CHECK: arraydestroy.body1:
    436 ; CHECK:   @objc_release
    437 ; CHECK-NOT: @objc_release
    438 ; CHECK: arraydestroy.done1:
    439 ; CHECK: @objc_release
    440 ; CHECK: ret void
    441 ; CHECK: }
    442 define void @test3b() {
    443 entry:
    444   %keys = alloca [2 x i8*], align 16
    445   %objs = alloca [2 x i8*], align 16
    446   
    447   %call1 = call i8* @returner()
    448   %tmp0 = tail call i8* @objc_retainAutoreleasedReturnValue(i8* %call1)
    449   %tmp1 = tail call i8* @objc_retain(i8* %call1)
    450 
    451   %objs.begin = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
    452   tail call i8* @objc_retain(i8* %call1)
    453   store i8* %call1, i8** %objs.begin, align 8
    454   %objs.elt = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 1
    455   tail call i8* @objc_retain(i8* %call1)
    456   store i8* %call1, i8** %objs.elt
    457 
    458   %call2 = call i8* @returner1()
    459   %call3 = call i8* @returner2()
    460   %keys.begin = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
    461   tail call i8* @objc_retain(i8* %call2)
    462   store i8* %call2, i8** %keys.begin, align 8
    463   %keys.elt = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 1
    464   tail call i8* @objc_retain(i8* %call3)
    465   store i8* %call3, i8** %keys.elt  
    466   
    467   %gep = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 2
    468   br label %arraydestroy.body
    469 
    470 arraydestroy.body:
    471   %arraydestroy.elementPast = phi i8** [ %gep, %entry ], [ %arraydestroy.element, %arraydestroy.body ]
    472   %arraydestroy.element = getelementptr inbounds i8** %arraydestroy.elementPast, i64 -1
    473   %destroy_tmp = load i8** %arraydestroy.element, align 8
    474   call void @objc_release(i8* %destroy_tmp), !clang.imprecise_release !0
    475   %objs_ptr = getelementptr inbounds [2 x i8*]* %objs, i64 0, i64 0
    476   %arraydestroy.cmp = icmp eq i8** %arraydestroy.element, %objs_ptr
    477   br i1 %arraydestroy.cmp, label %arraydestroy.done, label %arraydestroy.body
    478 
    479 arraydestroy.done:
    480   %gep1 = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 2
    481   br label %arraydestroy.body1
    482 
    483 arraydestroy.body1:
    484   %arraydestroy.elementPast1 = phi i8** [ %gep1, %arraydestroy.done ], [ %arraydestroy.element1, %arraydestroy.body1 ]
    485   %arraydestroy.element1 = getelementptr inbounds i8** %arraydestroy.elementPast1, i64 -1
    486   %destroy_tmp1 = load i8** %arraydestroy.element1, align 8
    487   call void @objc_release(i8* %destroy_tmp1), !clang.imprecise_release !0
    488   %keys_ptr = getelementptr inbounds [2 x i8*]* %keys, i64 0, i64 0
    489   %arraydestroy.cmp1 = icmp eq i8** %arraydestroy.element1, %keys_ptr
    490   br i1 %arraydestroy.cmp1, label %arraydestroy.done1, label %arraydestroy.body1
    491 
    492 arraydestroy.done1:
    493   call void @objc_release(i8* %call1), !clang.imprecise_release !0
    494   call void @objc_release(i8* %call1), !clang.imprecise_release !0
    495   ret void
    496 }
    497 
    498 !0 = metadata !{}
    499 
    500 declare i32 @__gxx_personality_v0(...)
    501