• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.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() {
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 i8 @unoptimizable1() {
55define i8 @unoptimizable1() {
56entry:
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() {
66define void @indirectLoads() {
67entry:
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() {
119define void @combiningBitCastWithLoad() {
120entry:
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() {
147define void @loadCombine() {
148enter:
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() {
164define void @loadCombine1() {
165enter:
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() {
181define void @loadCombine2() {
182enter:
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() {
198define void @loadCombine3() {
199enter:
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() {
215define i8 @unoptimizable2() {
216entry:
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() {
229define i8 @unoptimizable3() {
230entry:
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() {
241define i8 @unoptimizable4() {
242entry:
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() {
253define i8 @volatile1() {
254entry:
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() {
272define i8 @volatile2() {
273entry:
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() {
291define i8 @fun() {
292entry:
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
322declare void @foo(i8*)
323declare void @bar(i8)
324declare i8* @getPointer(i8*)
325declare void @_ZN1A3fooEv(%struct.A*)
326declare void @_ZN1AC1Ev(%struct.A*)
327declare i8* @llvm.invariant.group.barrier(i8*)
328
329; Function Attrs: nounwind
330declare void @llvm.assume(i1 %cmp.vtables) #0
331
332
333attributes #0 = { nounwind }
334; CHECK: ![[OneMD]] = !{!"other ptr"}
335!0 = !{!"magic ptr"}
336!1 = !{!"other ptr"}
337!2 = !{!"vtable_of_a"}
338