Taints the non-acquire RMW's store address with the load part
[oota-llvm.git] / test / Transforms / GVN / invariant.group.ll
1 ; RUN: opt < %s -gvn -S | FileCheck %s
2
3 %struct.A = type { i32 (...)** }
4 @_ZTV1A = available_externally unnamed_addr constant [3 x i8*] [i8* null, i8* bitcast (i8** @_ZTI1A to i8*), i8* bitcast (void (%struct.A*)* @_ZN1A3fooEv to i8*)], align 8
5 @_ZTI1A = external constant i8*
6
7 @unknownPtr = external global i8
8
9 ; CHECK-LABEL: define i8 @simple() {
10 define i8 @simple() {
11 entry:
12     %ptr = alloca i8
13     store i8 42, i8* %ptr, !invariant.group !0
14     call void @foo(i8* %ptr)
15
16     %a = load i8, i8* %ptr, !invariant.group !0
17     %b = load i8, i8* %ptr, !invariant.group !0
18     %c = load i8, i8* %ptr, !invariant.group !0
19 ; CHECK: ret i8 42
20     ret i8 %a
21 }
22
23 ; CHECK-LABEL: define i8 @optimizable1() {
24 define i8 @optimizable1() {
25 entry:
26     %ptr = alloca i8
27     store i8 42, i8* %ptr, !invariant.group !0
28     %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
29     %a = load i8, i8* %ptr, !invariant.group !0
30     
31     call void @foo(i8* %ptr2); call to use %ptr2
32 ; CHECK: ret i8 42
33     ret i8 %a
34 }
35
36 ; CHECK-LABEL: define i8 @optimizable2() {
37 define i8 @optimizable2() {
38 entry:
39     %ptr = alloca i8
40     store i8 42, i8* %ptr, !invariant.group !0
41     call void @foo(i8* %ptr)
42     
43     store i8 13, i8* %ptr ; can't use this store with invariant.group
44     %a = load i8, i8* %ptr 
45     call void @bar(i8 %a) ; call to use %a
46     
47     call void @foo(i8* %ptr)
48     %b = load i8, i8* %ptr, !invariant.group !0
49     
50 ; CHECK: ret i8 42
51     ret i8 %b
52 }
53
54 ; CHECK-LABEL: define i8 @unoptimizable1() {
55 define i8 @unoptimizable1() {
56 entry:
57     %ptr = alloca i8
58     store i8 42, i8* %ptr
59     call void @foo(i8* %ptr)
60     %a = load i8, i8* %ptr, !invariant.group !0
61 ; CHECK: ret i8 %a
62     ret i8 %a
63 }
64
65 ; CHECK-LABEL: define void @indirectLoads() {
66 define void @indirectLoads() {
67 entry:
68   %a = alloca %struct.A*, align 8
69   %0 = bitcast %struct.A** %a to i8*
70   
71   %call = call i8* @getPointer(i8* null) 
72   %1 = bitcast i8* %call to %struct.A*
73   call void @_ZN1AC1Ev(%struct.A* %1)
74   %2 = bitcast %struct.A* %1 to i8***
75   
76 ; CHECK: %vtable = load {{.*}} !invariant.group
77   %vtable = load i8**, i8*** %2, align 8, !invariant.group !2
78   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
79   call void @llvm.assume(i1 %cmp.vtables)
80   
81   store %struct.A* %1, %struct.A** %a, align 8
82   %3 = load %struct.A*, %struct.A** %a, align 8
83   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
84
85 ; CHECK: call void @_ZN1A3fooEv(
86   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
87   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
88   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
89   call void %5(%struct.A* %3)
90   %6 = load %struct.A*, %struct.A** %a, align 8
91   %7 = bitcast %struct.A* %6 to void (%struct.A*)***
92
93 ; CHECK: call void @_ZN1A3fooEv(
94   %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !2
95   %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0
96   %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8
97   
98   call void %8(%struct.A* %6)
99   %9 = load %struct.A*, %struct.A** %a, align 8
100   %10 = bitcast %struct.A* %9 to void (%struct.A*)***
101   
102   %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !2
103   %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0
104   %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8
105 ; CHECK: call void @_ZN1A3fooEv(
106   call void %11(%struct.A* %9)
107  
108   %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !2
109   %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0
110   %12 = bitcast i8** %vfn6 to void (%struct.A*)**
111   %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8
112 ; CHECK: call void @_ZN1A3fooEv(
113   call void %13(%struct.A* %9)
114   
115   ret void
116 }
117
118 ; CHECK-LABEL: define void @combiningBitCastWithLoad() {
119 define void @combiningBitCastWithLoad() {
120 entry:
121   %a = alloca %struct.A*, align 8
122   %0 = bitcast %struct.A** %a to i8*
123   
124   %call = call i8* @getPointer(i8* null) 
125   %1 = bitcast i8* %call to %struct.A*
126   call void @_ZN1AC1Ev(%struct.A* %1)
127   %2 = bitcast %struct.A* %1 to i8***
128   
129 ; CHECK: %vtable = load {{.*}} !invariant.group
130   %vtable = load i8**, i8*** %2, align 8, !invariant.group !2
131   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
132   
133   store %struct.A* %1, %struct.A** %a, align 8
134 ; CHECK-NOT: !invariant.group
135   %3 = load %struct.A*, %struct.A** %a, align 8
136   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
137
138   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !2
139   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
140   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
141   call void %5(%struct.A* %3)
142
143   ret void
144 }
145
146 ; CHECK-LABEL:define void @loadCombine() {
147 define void @loadCombine() {
148 enter:
149   %ptr = alloca i8
150   store i8 42, i8* %ptr
151   call void @foo(i8* %ptr)
152 ; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
153   %a = load i8, i8* %ptr, !invariant.group !0
154 ; CHECK-NOT: load
155   %b = load i8, i8* %ptr, !invariant.group !1
156 ; CHECK: call void @bar(i8 %[[A]])
157   call void @bar(i8 %a)
158 ; CHECK: call void @bar(i8 %[[A]])
159   call void @bar(i8 %b)
160   ret void
161 }
162
163 ; CHECK-LABEL: define void @loadCombine1() {
164 define void @loadCombine1() {
165 enter:
166   %ptr = alloca i8
167   store i8 42, i8* %ptr
168   call void @foo(i8* %ptr)
169 ; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
170   %c = load i8, i8* %ptr
171 ; CHECK-NOT: load
172   %d = load i8, i8* %ptr, !invariant.group !1
173 ; CHECK: call void @bar(i8 %[[D]])
174   call void @bar(i8 %c)
175 ; CHECK: call void @bar(i8 %[[D]])
176   call void @bar(i8 %d)
177   ret void
178 }
179
180 ; CHECK-LABEL: define void @loadCombine2() {    
181 define void @loadCombine2() {
182 enter:
183   %ptr = alloca i8
184   store i8 42, i8* %ptr
185   call void @foo(i8* %ptr)
186 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
187   %e = load i8, i8* %ptr, !invariant.group !1
188 ; CHECK-NOT: load
189   %f = load i8, i8* %ptr
190 ; CHECK: call void @bar(i8 %[[E]])
191   call void @bar(i8 %e)
192 ; CHECK: call void @bar(i8 %[[E]])
193   call void @bar(i8 %f)
194   ret void
195 }
196
197 ; CHECK-LABEL: define void @loadCombine3() {
198 define void @loadCombine3() {
199 enter:
200   %ptr = alloca i8
201   store i8 42, i8* %ptr
202   call void @foo(i8* %ptr)
203 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group ![[OneMD:[0-9]]]
204   %e = load i8, i8* %ptr, !invariant.group !1
205 ; CHECK-NOT: load
206   %f = load i8, i8* %ptr, !invariant.group !1
207 ; CHECK: call void @bar(i8 %[[E]])
208   call void @bar(i8 %e)
209 ; CHECK: call void @bar(i8 %[[E]])
210   call void @bar(i8 %f)
211   ret void
212 }
213
214 ; CHECK-LABEL: define i8 @unoptimizable2() {
215 define i8 @unoptimizable2() {
216 entry:
217     %ptr = alloca i8
218     store i8 42, i8* %ptr
219     call void @foo(i8* %ptr)
220     %a = load i8, i8* %ptr
221     call void @foo(i8* %ptr)
222     %b = load i8, i8* %ptr, !invariant.group !0
223     
224 ; CHECK: ret i8 %a
225     ret i8 %a
226 }
227
228 ; CHECK-LABEL: define i8 @unoptimizable3() {
229 define i8 @unoptimizable3() {
230 entry:
231     %ptr = alloca i8
232     store i8 42, i8* %ptr, !invariant.group !0
233     %ptr2 = call i8* @getPointer(i8* %ptr)
234     %a = load i8, i8* %ptr2, !invariant.group !0
235     
236 ; CHECK: ret i8 %a
237     ret i8 %a
238 }
239
240 ; CHECK-LABEL: define i8 @unoptimizable4() {
241 define i8 @unoptimizable4() {
242 entry:
243     %ptr = alloca i8
244     store i8 42, i8* %ptr, !invariant.group !0
245     %ptr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
246     %a = load i8, i8* %ptr2, !invariant.group !0
247     
248 ; CHECK: ret i8 %a
249     ret i8 %a
250 }
251
252 ; CHECK-LABEL: define i8 @volatile1() {
253 define i8 @volatile1() {
254 entry:
255     %ptr = alloca i8
256     store i8 42, i8* %ptr, !invariant.group !0
257     call void @foo(i8* %ptr)
258     %a = load i8, i8* %ptr, !invariant.group !0
259     %b = load volatile i8, i8* %ptr
260 ; CHECK: call void @bar(i8 %b)
261     call void @bar(i8 %b)
262
263     %c = load volatile i8, i8* %ptr, !invariant.group !0
264 ; FIXME: we could change %c to 42, preserving volatile load
265 ; CHECK: call void @bar(i8 %c)
266     call void @bar(i8 %c)
267 ; CHECK: ret i8 42
268     ret i8 %a
269 }
270
271 ; CHECK-LABEL: define i8 @volatile2() {
272 define i8 @volatile2() {
273 entry:
274     %ptr = alloca i8
275     store i8 42, i8* %ptr, !invariant.group !0
276     call void @foo(i8* %ptr)
277     %a = load i8, i8* %ptr, !invariant.group !0
278     %b = load volatile i8, i8* %ptr
279 ; CHECK: call void @bar(i8 %b)
280     call void @bar(i8 %b)
281
282     %c = load volatile i8, i8* %ptr, !invariant.group !0
283 ; FIXME: we could change %c to 42, preserving volatile load
284 ; CHECK: call void @bar(i8 %c)
285     call void @bar(i8 %c)
286 ; CHECK: ret i8 42
287     ret i8 %a
288 }
289
290 ; CHECK-LABEL: define i8 @fun() {
291 define i8 @fun() {
292 entry:
293     %ptr = alloca i8
294     store i8 42, i8* %ptr, !invariant.group !0
295     call void @foo(i8* %ptr)
296
297     %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
298 ; CHECK: call void @bar(i8 42)
299     call void @bar(i8 %a)
300     
301     call void @foo(i8* %ptr)
302     %b = load i8, i8* %ptr, !invariant.group !1 ; Can't assume anything, because group changed
303 ; CHECK: call void @bar(i8 %b)
304     call void @bar(i8 %b)
305     
306     %newPtr = call i8* @getPointer(i8* %ptr) 
307     %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
308 ; CHECK: call void @bar(i8 %c)
309     call void @bar(i8 %c)
310     
311     %unknownValue = load i8, i8* @unknownPtr
312 ; FIXME: Can assume that %unknownValue == 42
313 ; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
314     store i8 %unknownValue, i8* %ptr, !invariant.group !0 
315
316     %newPtr2 = call i8* @llvm.invariant.group.barrier(i8* %ptr)
317     %d = load i8, i8* %newPtr2, !invariant.group !0  ; Can't step through invariant.group.barrier to get value of %ptr
318 ; CHECK: ret i8 %d
319     ret i8 %d
320 }
321
322 declare void @foo(i8*)
323 declare void @bar(i8)
324 declare i8* @getPointer(i8*)
325 declare void @_ZN1A3fooEv(%struct.A*)
326 declare void @_ZN1AC1Ev(%struct.A*)
327 declare i8* @llvm.invariant.group.barrier(i8*)
328
329 ; Function Attrs: nounwind
330 declare void @llvm.assume(i1 %cmp.vtables) #0
331
332
333 attributes #0 = { nounwind }
334 ; CHECK: ![[OneMD]] = !{!"other ptr"}
335 !0 = !{!"magic ptr"}
336 !1 = !{!"other ptr"}
337 !2 = !{!"vtable_of_a"}