1 ; RUN: opt < %s -gvn -S | FileCheck %s
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*
7 @unknownPtr = external global i8
9 ; CHECK-LABEL: define i8 @simple() {
13 store i8 42, i8* %ptr, !invariant.group !0
14 call void @foo(i8* %ptr)
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
23 ; CHECK-LABEL: define i8 @optimizable1() {
24 define i8 @optimizable1() {
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
31 call void @foo(i8* %ptr2); call to use %ptr2
36 ; CHECK-LABEL: define i8 @optimizable2() {
37 define i8 @optimizable2() {
40 store i8 42, i8* %ptr, !invariant.group !0
41 call void @foo(i8* %ptr)
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
47 call void @foo(i8* %ptr)
48 %b = load i8, i8* %ptr, !invariant.group !0
54 ; CHECK-LABEL: define i1 @proveEqualityForStrip(
55 define 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
66 ; CHECK-LABEL: define i8 @unoptimizable1() {
67 define i8 @unoptimizable1() {
71 call void @foo(i8* %ptr)
72 %a = load i8, i8* %ptr, !invariant.group !0
77 ; CHECK-LABEL: define void @indirectLoads() {
78 define void @indirectLoads() {
80 %a = alloca %struct.A*, align 8
81 %0 = bitcast %struct.A** %a to i8*
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***
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)
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*)***
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*)***
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
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*)***
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)
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)
130 ; CHECK-LABEL: define void @combiningBitCastWithLoad() {
131 define void @combiningBitCastWithLoad() {
133 %a = alloca %struct.A*, align 8
134 %0 = bitcast %struct.A** %a to i8*
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***
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)
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*)***
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)
158 ; CHECK-LABEL:define void @loadCombine() {
159 define void @loadCombine() {
162 store i8 42, i8* %ptr
163 call void @foo(i8* %ptr)
164 ; CHECK: %[[A:.*]] = load i8, i8* %ptr, !invariant.group
165 %a = load i8, i8* %ptr, !invariant.group !0
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)
175 ; CHECK-LABEL: define void @loadCombine1() {
176 define void @loadCombine1() {
179 store i8 42, i8* %ptr
180 call void @foo(i8* %ptr)
181 ; CHECK: %[[D:.*]] = load i8, i8* %ptr, !invariant.group
182 %c = load i8, i8* %ptr
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)
192 ; CHECK-LABEL: define void @loadCombine2() {
193 define void @loadCombine2() {
196 store i8 42, i8* %ptr
197 call void @foo(i8* %ptr)
198 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
199 %e = load i8, i8* %ptr, !invariant.group !0
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)
209 ; CHECK-LABEL: define void @loadCombine3() {
210 define void @loadCombine3() {
213 store i8 42, i8* %ptr
214 call void @foo(i8* %ptr)
215 ; CHECK: %[[E:.*]] = load i8, i8* %ptr, !invariant.group
216 %e = load i8, i8* %ptr, !invariant.group !0
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)
226 ; CHECK-LABEL: define i8 @unoptimizable2() {
227 define i8 @unoptimizable2() {
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
240 ; CHECK-LABEL: define i8 @unoptimizable3() {
241 define i8 @unoptimizable3() {
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
252 ; CHECK-LABEL: define i8 @optimizable4() {
253 define i8 @optimizable4() {
256 store i8 42, i8* %ptr, !invariant.group !0
257 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
259 %a = load i8, i8* %ptr2, !invariant.group !0
265 ; CHECK-LABEL: define i8 @volatile1() {
266 define i8 @volatile1() {
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)
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)
284 ; CHECK-LABEL: define i8 @volatile2() {
285 define i8 @volatile2() {
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)
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)
303 ; CHECK-LABEL: define i8 @fun() {
307 store i8 42, i8* %ptr, !invariant.group !0
308 call void @foo(i8* %ptr)
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)
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)
319 %unknownValue = load i8, i8* @unknownPtr
320 ; FIXME: Can assume that %unknownValue == 42
321 ; CHECK: store i8 %unknownValue, i8* %ptr, !invariant.group !0
322 store i8 %unknownValue, i8* %ptr, !invariant.group !0
324 %newPtr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
326 %d = load i8, i8* %newPtr2, !invariant.group !0
327 ; CHECK: ret i8 %unknownValue
331 ; This test checks if invariant.group understands gep with zeros
332 ; CHECK-LABEL: define void @testGEP0() {
333 define 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
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
352 _Z1gR1A.exit: ; preds = %0, %5
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() {
360 define void @testGlobal() {
361 ; CHECK: %a = load i8, i8* @unknownPtr, !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, !invariant.group !0
365 %1 = load i8, i8* @unknownPtr, !invariant.group !0
366 call void @bar(i8 %1)
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)
379 ; And in the case it is not global
380 ; CHECK-LABEL: define void @testNotGlobal() {
381 define void @testNotGlobal() {
383 call void @foo(i8* %a)
384 ; CHECK: %b = load i8, i8* %a, !invariant.group !0
385 %b = load i8, i8* %a, !invariant.group !0
386 call void @foo2(i8* %a, i8 %b)
388 %1 = load i8, i8* %a, !invariant.group !0
389 ; CHECK: call void @bar(i8 %b)
390 call void @bar(i8 %1)
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)
404 ; CHECK-LABEL: define void @handling_loops()
405 define 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
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
420 ._crit_edge.preheader: ; preds = %.lr.ph.i
421 br label %._crit_edge
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
435 _Z2g2R1A.exit.loopexit: ; preds = %._crit_edge
436 br label %_Z2g2R1A.exit
438 _Z2g2R1A.exit: ; preds = %_Z2g2R1A.exit.loopexit, %.lr.ph.i, %0
443 declare void @foo(i8*)
444 declare void @foo2(i8*, i8)
445 declare void @bar(i8)
446 declare i8* @getPointer(i8*)
447 declare void @_ZN1A3fooEv(%struct.A*)
448 declare void @_ZN1AC1Ev(%struct.A*)
449 declare void @fooBit(i1*, i1)
451 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
452 declare i8* @llvm.strip.invariant.group.p0i8(i8*)
455 declare void @llvm.assume(i1 %cmp.vtables)