Home | History | Annotate | Download | only in ObjCARC
      1 ; RUN: opt -S -basicaa -objc-arc < %s | FileCheck %s
      2 
      3 declare i8* @objc_loadWeak(i8**)
      4 declare i8* @objc_loadWeakRetained(i8**)
      5 declare i8* @objc_storeWeak(i8**, i8*)
      6 declare i8* @objc_initWeak(i8**, i8*)
      7 declare void @use_pointer(i8*)
      8 declare void @callee()
      9 
     10 ; Basic redundant @objc_loadWeak elimination.
     11 
     12 ; CHECK:      define void @test0(i8** %p) {
     13 ; CHECK-NEXT:   %y = call i8* @objc_loadWeak(i8** %p)
     14 ; CHECK-NEXT:   call void @use_pointer(i8* %y)
     15 ; CHECK-NEXT:   ret void
     16 ; CHECK-NEXT: }
     17 define void @test0(i8** %p) {
     18   %x = call i8* @objc_loadWeak(i8** %p)
     19   %y = call i8* @objc_loadWeak(i8** %p)
     20   call void @use_pointer(i8* %y)
     21   ret void
     22 }
     23 
     24 ; DCE the @objc_loadWeak.
     25 
     26 ; CHECK:      define void @test1(i8** %p) {
     27 ; CHECK-NEXT:   %y = call i8* @objc_loadWeakRetained(i8** %p)
     28 ; CHECK-NEXT:   call void @use_pointer(i8* %y)
     29 ; CHECK-NEXT:   ret void
     30 ; CHECK-NEXT: }
     31 define void @test1(i8** %p) {
     32   %x = call i8* @objc_loadWeak(i8** %p)
     33   %y = call i8* @objc_loadWeakRetained(i8** %p)
     34   call void @use_pointer(i8* %y)
     35   ret void
     36 }
     37 
     38 ; Basic redundant @objc_loadWeakRetained elimination.
     39 
     40 ; CHECK:      define void @test2(i8** %p) {
     41 ; CHECK-NEXT:   %x = call i8* @objc_loadWeak(i8** %p)
     42 ; CHECK-NEXT:   store i8 3, i8* %x
     43 ; CHECK-NEXT:   %1 = tail call i8* @objc_retain(i8* %x)
     44 ; CHECK-NEXT:   call void @use_pointer(i8* %x)
     45 ; CHECK-NEXT:   ret void
     46 ; CHECK-NEXT: }
     47 define void @test2(i8** %p) {
     48   %x = call i8* @objc_loadWeak(i8** %p)
     49   store i8 3, i8* %x
     50   %y = call i8* @objc_loadWeakRetained(i8** %p)
     51   call void @use_pointer(i8* %y)
     52   ret void
     53 }
     54 
     55 ; Basic redundant @objc_loadWeakRetained elimination, this time
     56 ; with a readonly call instead of a store.
     57 
     58 ; CHECK:      define void @test3(i8** %p) {
     59 ; CHECK-NEXT:   %x = call i8* @objc_loadWeak(i8** %p)
     60 ; CHECK-NEXT:   call void @use_pointer(i8* %x) [[RO:#[0-9]+]]
     61 ; CHECK-NEXT:   %1 = tail call i8* @objc_retain(i8* %x)
     62 ; CHECK-NEXT:   call void @use_pointer(i8* %x)
     63 ; CHECK-NEXT:   ret void
     64 ; CHECK-NEXT: }
     65 define void @test3(i8** %p) {
     66   %x = call i8* @objc_loadWeak(i8** %p)
     67   call void @use_pointer(i8* %x) readonly
     68   %y = call i8* @objc_loadWeakRetained(i8** %p)
     69   call void @use_pointer(i8* %y)
     70   ret void
     71 }
     72 
     73 ; A regular call blocks redundant weak load elimination.
     74 
     75 ; CHECK:      define void @test4(i8** %p) {
     76 ; CHECK-NEXT:   %x = call i8* @objc_loadWeak(i8** %p)
     77 ; CHECK-NEXT:   call void @use_pointer(i8* %x) [[RO]]
     78 ; CHECK-NEXT:   call void @callee()
     79 ; CHECK-NEXT:   %y = call i8* @objc_loadWeak(i8** %p)
     80 ; CHECK-NEXT:   call void @use_pointer(i8* %y)
     81 ; CHECK-NEXT:   ret void
     82 ; CHECK-NEXT: }
     83 define void @test4(i8** %p) {
     84   %x = call i8* @objc_loadWeak(i8** %p)
     85   call void @use_pointer(i8* %x) readonly
     86   call void @callee()
     87   %y = call i8* @objc_loadWeak(i8** %p)
     88   call void @use_pointer(i8* %y)
     89   ret void
     90 }
     91 
     92 ; Store to load forwarding.
     93 
     94 ; CHECK:      define void @test5(i8** %p, i8* %n) {
     95 ; CHECK-NEXT:   %1 = call i8* @objc_storeWeak(i8** %p, i8* %n)
     96 ; CHECK-NEXT:   call void @use_pointer(i8* %n)
     97 ; CHECK-NEXT:   ret void
     98 ; CHECK-NEXT: }
     99 define void @test5(i8** %p, i8* %n) {
    100   call i8* @objc_storeWeak(i8** %p, i8* %n)
    101   %y = call i8* @objc_loadWeak(i8** %p)
    102   call void @use_pointer(i8* %y)
    103   ret void
    104 }
    105 
    106 ; Store to load forwarding with objc_initWeak.
    107 
    108 ; CHECK:      define void @test6(i8** %p, i8* %n) {
    109 ; CHECK-NEXT:   %1 = call i8* @objc_initWeak(i8** %p, i8* %n)
    110 ; CHECK-NEXT:   call void @use_pointer(i8* %n)
    111 ; CHECK-NEXT:   ret void
    112 ; CHECK-NEXT: }
    113 define void @test6(i8** %p, i8* %n) {
    114   call i8* @objc_initWeak(i8** %p, i8* %n)
    115   %y = call i8* @objc_loadWeak(i8** %p)
    116   call void @use_pointer(i8* %y)
    117   ret void
    118 }
    119 
    120 ; Don't forward if there's a may-alias store in the way.
    121 
    122 ; CHECK:      define void @test7(i8** %p, i8* %n, i8** %q, i8* %m) {
    123 ; CHECK-NEXT:   call i8* @objc_initWeak(i8** %p, i8* %n)
    124 ; CHECK-NEXT:   call i8* @objc_storeWeak(i8** %q, i8* %m)
    125 ; CHECK-NEXT:   %y = call i8* @objc_loadWeak(i8** %p)
    126 ; CHECK-NEXT:   call void @use_pointer(i8* %y)
    127 ; CHECK-NEXT:   ret void
    128 ; CHECK-NEXT: }
    129 define void @test7(i8** %p, i8* %n, i8** %q, i8* %m) {
    130   call i8* @objc_initWeak(i8** %p, i8* %n)
    131   call i8* @objc_storeWeak(i8** %q, i8* %m)
    132   %y = call i8* @objc_loadWeak(i8** %p)
    133   call void @use_pointer(i8* %y)
    134   ret void
    135 }
    136 
    137 ; CHECK: attributes #0 = { nounwind }
    138 ; CHECK: attributes [[RO]] = { readonly }
    139