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