Home | History | Annotate | Download | only in ObjCARC
      1 ; RUN: opt -S -objc-arc < %s | FileCheck %s
      2 
      3 declare i8* @objc_retain(i8*) nonlazybind
      4 declare void @objc_release(i8*) nonlazybind
      5 declare i8* @objc_retainBlock(i8*)
      6 
      7 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      8 ; Use by an instruction which copies the value is an escape if the             ;
      9 ; result is an escape. The current instructions with this property are:        ;
     10 ;                                                                              ;
     11 ; 1. BitCast.                                                                  ;
     12 ; 2. GEP.                                                                      ;
     13 ; 3. PhiNode.                                                                  ;
     14 ; 4. SelectInst.                                                               ;
     15 ;                                                                              ;
     16 ; Make sure that such instructions do not confuse the optimizer into removing  ;
     17 ; an objc_retainBlock that is needed.                                          ;
     18 ;                                                                              ;
     19 ; rdar://13273675. (With extra test cases to handle bitcast, phi, and select.  ;
     20 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
     21 
     22 define void @bitcasttest(i8* %storage, void (...)* %block)  {
     23 ; CHECK: define void @bitcasttest
     24 entry:
     25   %t1 = bitcast void (...)* %block to i8*
     26 ; CHECK-NOT: tail call i8* @objc_retain
     27   %t2 = tail call i8* @objc_retain(i8* %t1)
     28 ; CHECK: tail call i8* @objc_retainBlock
     29   %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
     30   %t4 = bitcast i8* %storage to void (...)**
     31   %t5 = bitcast i8* %t3 to void (...)*
     32   store void (...)* %t5, void (...)** %t4, align 8
     33 ; CHECK-NOT: call void @objc_release
     34   call void @objc_release(i8* %t1)
     35   ret void
     36 }
     37 
     38 define void @geptest(void (...)** %storage_array, void (...)* %block)  {
     39 ; CHECK: define void @geptest
     40 entry:
     41   %t1 = bitcast void (...)* %block to i8*
     42 ; CHECK-NOT: tail call i8* @objc_retain
     43   %t2 = tail call i8* @objc_retain(i8* %t1)
     44 ; CHECK: tail call i8* @objc_retainBlock
     45   %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
     46   %t4 = bitcast i8* %t3 to void (...)*
     47   
     48   %storage = getelementptr inbounds void (...)** %storage_array, i64 0
     49   
     50   store void (...)* %t4, void (...)** %storage, align 8
     51 ; CHECK-NOT: call void @objc_release
     52   call void @objc_release(i8* %t1)
     53   ret void
     54 }
     55 
     56 define void @selecttest(void (...)** %store1, void (...)** %store2,
     57                         void (...)* %block) {
     58 ; CHECK: define void @selecttest
     59 entry:
     60   %t1 = bitcast void (...)* %block to i8*
     61 ; CHECK-NOT: tail call i8* @objc_retain
     62   %t2 = tail call i8* @objc_retain(i8* %t1)
     63 ; CHECK: tail call i8* @objc_retainBlock
     64   %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
     65   %t4 = bitcast i8* %t3 to void (...)*
     66   %store = select i1 undef, void (...)** %store1, void (...)** %store2
     67   store void (...)* %t4, void (...)** %store, align 8
     68 ; CHECK-NOT: call void @objc_release
     69   call void @objc_release(i8* %t1)
     70   ret void
     71 }
     72 
     73 define void @phinodetest(void (...)** %storage1,
     74                          void (...)** %storage2,
     75                          void (...)* %block) {
     76 ; CHECK: define void @phinodetest
     77 entry:
     78   %t1 = bitcast void (...)* %block to i8*
     79 ; CHECK-NOT: tail call i8* @objc_retain
     80   %t2 = tail call i8* @objc_retain(i8* %t1)
     81 ; CHECK: tail call i8* @objc_retainBlock
     82   %t3 = tail call i8* @objc_retainBlock(i8* %t1), !clang.arc.copy_on_escape !0
     83   %t4 = bitcast i8* %t3 to void (...)*
     84   br i1 undef, label %store1_set, label %store2_set
     85 
     86 store1_set:
     87   br label %end
     88 
     89 store2_set:
     90   br label %end
     91 
     92 end:
     93   %storage = phi void (...)** [ %storage1, %store1_set ], [ %storage2, %store2_set]
     94   store void (...)* %t4, void (...)** %storage, align 8
     95 ; CHECK-NOT: call void @objc_release
     96   call void @objc_release(i8* %t1)
     97   ret void
     98 }
     99 
    100 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    101 ; This test makes sure that we do not hang clang when visiting a use ;
    102 ; cycle caused by phi nodes during objc-arc analysis. *NOTE* This    ;
    103 ; test case looks a little convoluted since it was produced by	     ;
    104 ; bugpoint.							     ;
    105 ; 								     ;
    106 ; bugzilla://14551						     ;
    107 ; rdar://12851911						     ;
    108 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    109 
    110 define void @phinode_use_cycle(i8* %block) uwtable optsize ssp {
    111 ; CHECK: define void @phinode_use_cycle(i8* %block)
    112 entry:
    113   br label %for.body
    114 
    115 for.body:                                         ; preds = %if.then, %for.body, %entry
    116   %block.05 = phi void (...)* [ null, %entry ], [ %1, %if.then ], [ %block.05, %for.body ]
    117   br i1 undef, label %for.body, label %if.then
    118 
    119 if.then:                                          ; preds = %for.body
    120   %0 = call i8* @objc_retainBlock(i8* %block), !clang.arc.copy_on_escape !0
    121   %1 = bitcast i8* %0 to void (...)*
    122   %2 = bitcast void (...)* %block.05 to i8*
    123   call void @objc_release(i8* %2) nounwind, !clang.imprecise_release !0
    124   br label %for.body
    125 }
    126 
    127 !0 = metadata !{}
    128