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