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