• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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