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