1; RUN: opt -S -basicaa -objc-arc < %s | FileCheck %s 2 3declare i8* @objc_loadWeak(i8**) 4declare i8* @objc_loadWeakRetained(i8**) 5declare i8* @objc_storeWeak(i8**, i8*) 6declare i8* @objc_initWeak(i8**, i8*) 7declare void @use_pointer(i8*) 8declare 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: } 17define 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: } 31define 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: } 47define 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: } 65define 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: } 83define 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: } 99define 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: } 113define 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: } 129define 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