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.invariant.group.barrier(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 i8 @unoptimizable1() {
55 define i8 @unoptimizable1() {
59 call void @foo(i8* %ptr)
60 %a = load i8, i8* %ptr, !invariant.group !0
65 ; CHECK-LABEL: define void @indirectLoads() {
66 define void @indirectLoads() {
68 %a = alloca %struct.A*, align 8
69 %0 = bitcast %struct.A** %a to i8*
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***
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)
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*)***
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*)***
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
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*)***
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)
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)
118 ; CHECK-LABEL: define void @combiningBitCastWithLoad() {
119 define void @combiningBitCastWithLoad() {
121 %a = alloca %struct.A*, align 8
122 %0 = bitcast %struct.A** %a to i8*
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***
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)
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*)***
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)
146 ; CHECK-LABEL:define void @loadCombine() {
147 define void @loadCombine() {
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
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)
163 ; CHECK-LABEL: define void @loadCombine1() {
164 define void @loadCombine1() {
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
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)
180 ; CHECK-LABEL: define void @loadCombine2() {
181 define void @loadCombine2() {
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
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)
197 ; CHECK-LABEL: define void @loadCombine3() {
198 define void @loadCombine3() {
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
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)
214 ; CHECK-LABEL: define i8 @unoptimizable2() {
215 define i8 @unoptimizable2() {
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
228 ; CHECK-LABEL: define i8 @unoptimizable3() {
229 define i8 @unoptimizable3() {
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
240 ; CHECK-LABEL: define i8 @unoptimizable4() {
241 define i8 @unoptimizable4() {
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
252 ; CHECK-LABEL: define i8 @volatile1() {
253 define i8 @volatile1() {
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)
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)
271 ; CHECK-LABEL: define i8 @volatile2() {
272 define i8 @volatile2() {
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)
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)
290 ; CHECK-LABEL: define i8 @fun() {
294 store i8 42, i8* %ptr, !invariant.group !0
295 call void @foo(i8* %ptr)
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)
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)
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)
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
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
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*)
329 ; Function Attrs: nounwind
330 declare void @llvm.assume(i1 %cmp.vtables) #0
333 attributes #0 = { nounwind }
334 ; CHECK: ![[OneMD]] = !{!"other ptr"}
337 !2 = !{!"vtable_of_a"}