[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / Transforms / NewGVN / invariant.group.ll
blob78e61a2f2b681aeab0e1ec56b2d88fc42005a37a
1 ; XFAIL: *
2 ; RUN: opt < %s -newgvn -S | FileCheck %s
4 %struct.A = type { i32 (...)** }
5 @_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
6 @_ZTI1A = external constant i8*
8 @unknownPtr = external global i8
10 ; CHECK-LABEL: define i8 @simple() {
11 define i8 @simple() {
12 entry:
13     %ptr = alloca i8
14     store i8 42, i8* %ptr, !invariant.group !0
15     call void @foo(i8* %ptr)
17     %a = load i8, i8* %ptr, !invariant.group !0
18     %b = load i8, i8* %ptr, !invariant.group !0
19     %c = load i8, i8* %ptr, !invariant.group !0
20 ; CHECK: ret i8 42
21     ret i8 %a
24 ; CHECK-LABEL: define i8 @optimizable1() {
25 define i8 @optimizable1() {
26 entry:
27     %ptr = alloca i8
28     store i8 42, i8* %ptr, !invariant.group !0
29     %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
30     %a = load i8, i8* %ptr, !invariant.group !0
31     
32     call void @foo(i8* %ptr2); call to use %ptr2
33 ; CHECK: ret i8 42
34     ret i8 %a
37 ; CHECK-LABEL: define i8 @optimizable2() {
38 define i8 @optimizable2() {
39 entry:
40     %ptr = alloca i8
41     store i8 42, i8* %ptr, !invariant.group !0
42     call void @foo(i8* %ptr)
43     
44     store i8 13, i8* %ptr ; can't use this store with invariant.group
45     %a = load i8, i8* %ptr 
46     call void @bar(i8 %a) ; call to use %a
47     
48     call void @foo(i8* %ptr)
49     %b = load i8, i8* %ptr, !invariant.group !0
50     
51 ; CHECK: ret i8 42
52     ret i8 %b
55 ; CHECK-LABEL: define i1 @proveEqualityForStrip(
56 define i1 @proveEqualityForStrip(i8* %a) {
57 ; FIXME: The first call could be also removed by GVN. Right now
58 ; DCE removes it. The second call is CSE'd with the first one.
59 ; CHECK: %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
60   %b1 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
61 ; CHECK-NOT: llvm.strip.invariant.group
62   %b2 = call i8* @llvm.strip.invariant.group.p0i8(i8* %a)
63   %r = icmp eq i8* %b1, %b2
64 ; CHECK: ret i1 true
65   ret i1 %r
68 ; CHECK-LABEL: define i8 @unoptimizable1() {
69 define i8 @unoptimizable1() {
70 entry:
71     %ptr = alloca i8
72     store i8 42, i8* %ptr
73     call void @foo(i8* %ptr)
74     %a = load i8, i8* %ptr, !invariant.group !0
75 ; CHECK: ret i8 %a
76     ret i8 %a
79 ; CHECK-LABEL: define void @indirectLoads() {
80 define void @indirectLoads() {
81 entry:
82   %a = alloca %struct.A*, align 8
83   %0 = bitcast %struct.A** %a to i8*
84   
85   %call = call i8* @getPointer(i8* null) 
86   %1 = bitcast i8* %call to %struct.A*
87   call void @_ZN1AC1Ev(%struct.A* %1)
88   %2 = bitcast %struct.A* %1 to i8***
89   
90 ; CHECK: %vtable = load {{.*}} !invariant.group
91   %vtable = load i8**, i8*** %2, align 8, !invariant.group !0
92   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
93   call void @llvm.assume(i1 %cmp.vtables)
94   
95   store %struct.A* %1, %struct.A** %a, align 8
96   %3 = load %struct.A*, %struct.A** %a, align 8
97   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
99 ; CHECK: call void @_ZN1A3fooEv(
100   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0
101   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
102   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
103   call void %5(%struct.A* %3)
104   %6 = load %struct.A*, %struct.A** %a, align 8
105   %7 = bitcast %struct.A* %6 to void (%struct.A*)***
107 ; CHECK: call void @_ZN1A3fooEv(
108   %vtable2 = load void (%struct.A*)**, void (%struct.A*)*** %7, align 8, !invariant.group !0
109   %vfn3 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable2, i64 0
110   %8 = load void (%struct.A*)*, void (%struct.A*)** %vfn3, align 8
111   
112   call void %8(%struct.A* %6)
113   %9 = load %struct.A*, %struct.A** %a, align 8
114   %10 = bitcast %struct.A* %9 to void (%struct.A*)***
115   
116   %vtable4 = load void (%struct.A*)**, void (%struct.A*)*** %10, align 8, !invariant.group !0
117   %vfn5 = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable4, i64 0
118   %11 = load void (%struct.A*)*, void (%struct.A*)** %vfn5, align 8
119 ; CHECK: call void @_ZN1A3fooEv(
120   call void %11(%struct.A* %9)
122   %vtable5 = load i8**, i8*** %2, align 8, !invariant.group !0
123   %vfn6 = getelementptr inbounds i8*, i8** %vtable5, i64 0
124   %12 = bitcast i8** %vfn6 to void (%struct.A*)**
125   %13 = load void (%struct.A*)*, void (%struct.A*)** %12, align 8
126 ; CHECK: call void @_ZN1A3fooEv(
127   call void %13(%struct.A* %9)
128   
129   ret void
132 ; CHECK-LABEL: define void @combiningBitCastWithLoad() {
133 define void @combiningBitCastWithLoad() {
134 entry:
135   %a = alloca %struct.A*, align 8
136   %0 = bitcast %struct.A** %a to i8*
137   
138   %call = call i8* @getPointer(i8* null) 
139   %1 = bitcast i8* %call to %struct.A*
140   call void @_ZN1AC1Ev(%struct.A* %1)
141   %2 = bitcast %struct.A* %1 to i8***
142   
143 ; CHECK: %vtable = load {{.*}} !invariant.group
144   %vtable = load i8**, i8*** %2, align 8, !invariant.group !0
145   %cmp.vtables = icmp eq i8** %vtable, getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2)
146   
147   store %struct.A* %1, %struct.A** %a, align 8
148 ; CHECK-NOT: !invariant.group
149   %3 = load %struct.A*, %struct.A** %a, align 8
150   %4 = bitcast %struct.A* %3 to void (%struct.A*)***
152   %vtable1 = load void (%struct.A*)**, void (%struct.A*)*** %4, align 8, !invariant.group !0
153   %vfn = getelementptr inbounds void (%struct.A*)*, void (%struct.A*)** %vtable1, i64 0
154   %5 = load void (%struct.A*)*, void (%struct.A*)** %vfn, align 8
155   call void %5(%struct.A* %3)
157   ret void
160 ; CHECK-LABEL:define void @loadCombine() {
161 define void @loadCombine() {
162 enter:
163   %ptr = alloca i8
164   store i8 42, i8* %ptr
165   call void @foo(i8* %ptr)
166 ; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
167   %a = load i8, i8* %ptr, !invariant.group !0
168 ; CHECK-NOT: load
169   %b = load i8, i8* %ptr, !invariant.group !0
170 ; CHECK: call void @bar(i8 %[[A]])
171   call void @bar(i8 %a)
172 ; CHECK: call void @bar(i8 %[[A]])
173   call void @bar(i8 %b)
174   ret void
177 ; CHECK-LABEL: define void @loadCombine1() {
178 define void @loadCombine1() {
179 enter:
180   %ptr = alloca i8
181   store i8 42, i8* %ptr
182   call void @foo(i8* %ptr)
183 ; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
184   %c = load i8, i8* %ptr
185 ; CHECK-NOT: load
186   %d = load i8, i8* %ptr, !invariant.group !0
187 ; CHECK: call void @bar(i8 %[[D]])
188   call void @bar(i8 %c)
189 ; CHECK: call void @bar(i8 %[[D]])
190   call void @bar(i8 %d)
191   ret void
194 ; CHECK-LABEL: define void @loadCombine2() {    
195 define void @loadCombine2() {
196 enter:
197   %ptr = alloca i8
198   store i8 42, i8* %ptr
199   call void @foo(i8* %ptr)
200 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
201   %e = load i8, i8* %ptr, !invariant.group !0
202 ; CHECK-NOT: load
203   %f = load i8, i8* %ptr
204 ; CHECK: call void @bar(i8 %[[E]])
205   call void @bar(i8 %e)
206 ; CHECK: call void @bar(i8 %[[E]])
207   call void @bar(i8 %f)
208   ret void
211 ; CHECK-LABEL: define void @loadCombine3() {
212 define void @loadCombine3() {
213 enter:
214   %ptr = alloca i8
215   store i8 42, i8* %ptr
216   call void @foo(i8* %ptr)
217 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
218   %e = load i8, i8* %ptr, !invariant.group !0
219 ; CHECK-NOT: load
220   %f = load i8, i8* %ptr, !invariant.group !0
221 ; CHECK: call void @bar(i8 %[[E]])
222   call void @bar(i8 %e)
223 ; CHECK: call void @bar(i8 %[[E]])
224   call void @bar(i8 %f)
225   ret void
228 ; CHECK-LABEL: define i8 @unoptimizable2() {
229 define i8 @unoptimizable2() {
230 entry:
231     %ptr = alloca i8
232     store i8 42, i8* %ptr
233     call void @foo(i8* %ptr)
234     %a = load i8, i8* %ptr
235     call void @foo(i8* %ptr)
236     %b = load i8, i8* %ptr, !invariant.group !0
237     
238 ; CHECK: ret i8 %a
239     ret i8 %a
242 ; CHECK-LABEL: define i8 @unoptimizable3() {
243 define i8 @unoptimizable3() {
244 entry:
245     %ptr = alloca i8
246     store i8 42, i8* %ptr, !invariant.group !0
247     %ptr2 = call i8* @getPointer(i8* %ptr)
248     %a = load i8, i8* %ptr2, !invariant.group !0
249     
250 ; CHECK: ret i8 %a
251     ret i8 %a
254 ; CHECK-LABEL: define i8 @optimizable4() {
255 define i8 @optimizable4() {
256 entry:
257     %ptr = alloca i8
258     store i8 42, i8* %ptr, !invariant.group !0
259     %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
260 ; CHECK-NOT: load
261     %a = load i8, i8* %ptr2, !invariant.group !0
262     
263 ; CHECK: ret i8 42
264     ret i8 %a
267 ; CHECK-LABEL: define i8 @volatile1() {
268 define i8 @volatile1() {
269 entry:
270     %ptr = alloca i8
271     store i8 42, i8* %ptr, !invariant.group !0
272     call void @foo(i8* %ptr)
273     %a = load i8, i8* %ptr, !invariant.group !0
274     %b = load volatile i8, i8* %ptr
275 ; CHECK: call void @bar(i8 %b)
276     call void @bar(i8 %b)
278     %c = load volatile i8, i8* %ptr, !invariant.group !0
279 ; FIXME: we could change %c to 42, preserving volatile load
280 ; CHECK: call void @bar(i8 %c)
281     call void @bar(i8 %c)
282 ; CHECK: ret i8 42
283     ret i8 %a
286 ; CHECK-LABEL: define i8 @volatile2() {
287 define i8 @volatile2() {
288 entry:
289     %ptr = alloca i8
290     store i8 42, i8* %ptr, !invariant.group !0
291     call void @foo(i8* %ptr)
292     %a = load i8, i8* %ptr, !invariant.group !0
293     %b = load volatile i8, i8* %ptr
294 ; CHECK: call void @bar(i8 %b)
295     call void @bar(i8 %b)
297     %c = load volatile i8, i8* %ptr, !invariant.group !0
298 ; FIXME: we could change %c to 42, preserving volatile load
299 ; CHECK: call void @bar(i8 %c)
300     call void @bar(i8 %c)
301 ; CHECK: ret i8 42
302     ret i8 %a
305 ; CHECK-LABEL: define i8 @fun() {
306 define i8 @fun() {
307 entry:
308     %ptr = alloca i8
309     store i8 42, i8* %ptr, !invariant.group !0
310     call void @foo(i8* %ptr)
312     %a = load i8, i8* %ptr, !invariant.group !0 ; Can assume that value under %ptr didn't change
313 ; CHECK: call void @bar(i8 42)
314     call void @bar(i8 %a)
316     %newPtr = call i8* @getPointer(i8* %ptr) 
317     %c = load i8, i8* %newPtr, !invariant.group !0 ; Can't assume anything, because we only have information about %ptr
318 ; CHECK: call void @bar(i8 %c)
319     call void @bar(i8 %c)
320     
321     %unknownValue = load i8, i8* @unknownPtr
322 ; FIXME: Can assume that %unknownValue == 42
323 ; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
324     store i8 %unknownValue, i8* %ptr, !invariant.group !0 
326     %newPtr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
327 ; CHECK-NOT: load
328     %d = load i8, i8* %newPtr2, !invariant.group !0
329 ; CHECK: ret i8 %unknownValue
330     ret i8 %d
333 ; This test checks if invariant.group understands gep with zeros
334 ; CHECK-LABEL: define void @testGEP0() {
335 define void @testGEP0() {
336   %a = alloca %struct.A, align 8
337   %1 = bitcast %struct.A* %a to i8*
338   %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0
339   store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0
340 ; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a)
341   call void @_ZN1A3fooEv(%struct.A* nonnull dereferenceable(8) %a) ; This call may change vptr
342   %3 = load i8, i8* @unknownPtr, align 4
343   %4 = icmp eq i8 %3, 0
344   br i1 %4, label %_Z1gR1A.exit, label %5
346 ; This should be devirtualized by invariant.group
347   %6 = bitcast %struct.A* %a to void (%struct.A*)***
348   %7 = load void (%struct.A*)**, void (%struct.A*)*** %6, align 8, !invariant.group !0
349   %8 = load void (%struct.A*)*, void (%struct.A*)** %7, align 8
350 ; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a)
351   call void %8(%struct.A* nonnull %a)
352   br label %_Z1gR1A.exit
354 _Z1gR1A.exit:                                     ; preds = %0, %5
355   ret void
358 ; Check if no optimizations are performed with global pointers.
359 ; FIXME: we could do the optimizations if we would check if dependency comes
360 ; from the same function.
361 ; CHECK-LABEL: define void @testGlobal() {
362 define void @testGlobal() {
363 ; CHECK:  %a = load i8, i8* @unknownPtr, !invariant.group !0
364    %a = load i8, i8* @unknownPtr, !invariant.group !0
365    call void @foo2(i8* @unknownPtr, i8 %a)
366 ; CHECK:  %1 = load i8, i8* @unknownPtr, !invariant.group !0
367    %1 = load i8, i8* @unknownPtr, !invariant.group !0
368    call void @bar(i8 %1)
370    %b0 = bitcast i8* @unknownPtr to i1*
371    call void @fooBit(i1* %b0, i1 1)
372 ; Adding regex because of canonicalization of bitcasts
373 ; CHECK: %2 = load i1, i1* {{.*}}, !invariant.group !0
374    %2 = load i1, i1* %b0, !invariant.group !0
375    call void @fooBit(i1* %b0, i1 %2)
376 ; CHECK:  %3 = load i1, i1* {{.*}}, !invariant.group !0
377    %3 = load i1, i1* %b0, !invariant.group !0
378    call void @fooBit(i1* %b0, i1 %3)
379    ret void
381 ; And in the case it is not global
382 ; CHECK-LABEL: define void @testNotGlobal() {
383 define void @testNotGlobal() {
384    %a = alloca i8
385    call void @foo(i8* %a)
386 ; CHECK:  %b = load i8, i8* %a, !invariant.group !0
387    %b = load i8, i8* %a, !invariant.group !0
388    call void @foo2(i8* %a, i8 %b)
390    %1 = load i8, i8* %a, !invariant.group !0
391 ; CHECK: call void @bar(i8 %b)
392    call void @bar(i8 %1)
394    %b0 = bitcast i8* %a to i1*
395    call void @fooBit(i1* %b0, i1 1)
396 ; CHECK: %1 = trunc i8 %b to i1
397    %2 = load i1, i1* %b0, !invariant.group !0
398 ; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1)
399    call void @fooBit(i1* %b0, i1 %2)
400    %3 = load i1, i1* %b0, !invariant.group !0
401 ; CHECK-NEXT: call void @fooBit(i1* %b0, i1 %1)
402    call void @fooBit(i1* %b0, i1 %3)
403    ret void
406 ; CHECK-LABEL: define void @handling_loops()
407 define void @handling_loops() {
408   %a = alloca %struct.A, align 8
409   %1 = bitcast %struct.A* %a to i8*
410   %2 = getelementptr inbounds %struct.A, %struct.A* %a, i64 0, i32 0
411   store i32 (...)** bitcast (i8** getelementptr inbounds ([3 x i8*], [3 x i8*]* @_ZTV1A, i64 0, i64 2) to i32 (...)**), i32 (...)*** %2, align 8, !invariant.group !0
412   %3 = load i8, i8* @unknownPtr, align 4
413   %4 = icmp sgt i8 %3, 0
414   br i1 %4, label %.lr.ph.i, label %_Z2g2R1A.exit
416 .lr.ph.i:                                         ; preds = %0
417   %5 = bitcast %struct.A* %a to void (%struct.A*)***
418   %6 = load i8, i8* @unknownPtr, align 4
419   %7 = icmp sgt i8 %6, 1
420   br i1 %7, label %._crit_edge.preheader, label %_Z2g2R1A.exit
422 ._crit_edge.preheader:                            ; preds = %.lr.ph.i
423   br label %._crit_edge
425 ._crit_edge:                                      ; preds = %._crit_edge.preheader, %._crit_edge
426   %8 = phi i8 [ %10, %._crit_edge ], [ 1, %._crit_edge.preheader ]
427   %.pre = load void (%struct.A*)**, void (%struct.A*)*** %5, align 8, !invariant.group !0
428   %9 = load void (%struct.A*)*, void (%struct.A*)** %.pre, align 8
429   ; CHECK: call void @_ZN1A3fooEv(%struct.A* nonnull %a)
430   call void %9(%struct.A* nonnull %a) #3
431   ; CHECK-NOT: call void %
432   %10 = add nuw nsw i8 %8, 1
433   %11 = load i8, i8* @unknownPtr, align 4
434   %12 = icmp slt i8 %10, %11
435   br i1 %12, label %._crit_edge, label %_Z2g2R1A.exit.loopexit
437 _Z2g2R1A.exit.loopexit:                           ; preds = %._crit_edge
438   br label %_Z2g2R1A.exit
440 _Z2g2R1A.exit:                                    ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0
441   ret void
445 declare void @foo(i8*)
446 declare void @foo2(i8*, i8)
447 declare void @bar(i8)
448 declare i8* @getPointer(i8*)
449 declare void @_ZN1A3fooEv(%struct.A*)
450 declare void @_ZN1AC1Ev(%struct.A*)
451 declare void @fooBit(i1*, i1)
453 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
455 ; Function Attrs: nounwind
456 declare void @llvm.assume(i1 %cmp.vtables) #0
459 attributes #0 = { nounwind }
460 !0 = !{}