1 ; RUN: opt -aa-pipeline=basic-aa -passes='print<memoryssa-walker>' -verify-memoryssa < %s 2>&1 | FileCheck %s
3 @g = external global i32
5 ; CHECK-LABEL: define {{.*}} @global(
7 ; CHECK: 1 = MemoryDef(liveOnEntry)
8 ; CHECK-NEXT: store i32 0
9 store i32 0, i32* @g, align 4, !invariant.group !0
11 ; CHECK: 2 = MemoryDef(1)
12 ; CHECK-NEXT: call void @clobber
13 call void @clobber(i32* @g)
15 ; FIXME: this could be clobbered by 1 if we walked the instruction list for loads/stores to @g.
16 ; But we can't look at the uses of @g in a function analysis.
17 ; CHECK: MemoryUse(2) {{.*}} clobbered by 2
18 ; CHECK-NEXT: %1 = load i32
19 %1 = load i32, i32* @g, align 4, !invariant.group !0
23 ; CHECK-LABEL: define {{.*}} @global2(
24 define i32 @global2() {
25 ; CHECK: 1 = MemoryDef(liveOnEntry)
26 ; CHECK-NEXT: store i32 0
27 store i32 0, i32* inttoptr (i64 ptrtoint (i32* @g to i64) to i32*), align 4, !invariant.group !0
29 ; CHECK: 2 = MemoryDef(1)
30 ; CHECK-NEXT: call void @clobber
31 call void @clobber(i32* inttoptr (i64 ptrtoint (i32* @g to i64) to i32*))
33 ; FIXME: this could be clobbered by 1 if we walked the instruction list for loads/stores to @g.
34 ; But we can't look at the uses of @g in a function analysis.
35 ; CHECK: MemoryUse(2) {{.*}} clobbered by 2
36 ; CHECK-NEXT: %1 = load i32
37 %1 = load i32, i32* inttoptr (i64 ptrtoint (i32* @g to i64) to i32*), align 4, !invariant.group !0
41 ; CHECK-LABEL: define {{.*}} @foo(
42 define i32 @foo(i32* %a) {
43 ; CHECK: 1 = MemoryDef(liveOnEntry)
44 ; CHECK-NEXT: store i32 0
45 store i32 0, i32* %a, align 4, !invariant.group !0
47 ; CHECK: 2 = MemoryDef(1)
48 ; CHECK-NEXT: store i32 1
49 store i32 1, i32* @g, align 4
51 %1 = bitcast i32* %a to i8*
52 ; CHECK: 3 = MemoryDef(2)
53 ; CHECK-NEXT: %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
54 %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
55 %a32 = bitcast i8* %a8 to i32*
57 ; This have to be MemoryUse(2), because we can't skip the barrier based on
60 ; CHECK-NEXT: %2 = load i32
61 %2 = load i32, i32* %a32, align 4, !invariant.group !0
65 ; CHECK-LABEL: define {{.*}} @volatile1(
66 define void @volatile1(i32* %a) {
67 ; CHECK: 1 = MemoryDef(liveOnEntry)
68 ; CHECK-NEXT: store i32 0
69 store i32 0, i32* %a, align 4, !invariant.group !0
71 ; CHECK: 2 = MemoryDef(1)
72 ; CHECK-NEXT: call void @clobber
73 call void @clobber(i32* %a)
75 ; CHECK: 3 = MemoryDef(2){{.*}} clobbered by 2
76 ; CHECK-NEXT: load volatile
77 %b = load volatile i32, i32* %a, align 4, !invariant.group !0
82 ; CHECK-LABEL: define {{.*}} @volatile2(
83 define void @volatile2(i32* %a) {
84 ; CHECK: 1 = MemoryDef(liveOnEntry)
85 ; CHECK-NEXT: store volatile i32 0
86 store volatile i32 0, i32* %a, align 4, !invariant.group !0
88 ; CHECK: 2 = MemoryDef(1)
89 ; CHECK-NEXT: call void @clobber
90 call void @clobber(i32* %a)
92 ; CHECK: MemoryUse(2){{.*}} clobbered by 2
93 ; CHECK-NEXT: load i32
94 %b = load i32, i32* %a, align 4, !invariant.group !0
99 ; CHECK-LABEL: define {{.*}} @skipBarrier(
100 define i32 @skipBarrier(i32* %a) {
101 ; CHECK: 1 = MemoryDef(liveOnEntry)
102 ; CHECK-NEXT: store i32 0
103 store i32 0, i32* %a, align 4, !invariant.group !0
105 %1 = bitcast i32* %a to i8*
106 ; CHECK: 2 = MemoryDef(1)
107 ; CHECK-NEXT: %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
108 %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
109 %a32 = bitcast i8* %a8 to i32*
111 ; We can skip the barrier only if the "skip" is not based on !invariant.group.
112 ; CHECK: MemoryUse(1)
113 ; CHECK-NEXT: %2 = load i32
114 %2 = load i32, i32* %a32, align 4, !invariant.group !0
118 ; CHECK-LABEL: define {{.*}} @skipBarrier2(
119 define i32 @skipBarrier2(i32* %a) {
121 ; CHECK: MemoryUse(liveOnEntry)
122 ; CHECK-NEXT: %v = load i32
123 %v = load i32, i32* %a, align 4, !invariant.group !0
125 %1 = bitcast i32* %a to i8*
126 ; CHECK: 1 = MemoryDef(liveOnEntry)
127 ; CHECK-NEXT: %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
128 %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
129 %a32 = bitcast i8* %a8 to i32*
131 ; We can skip the barrier only if the "skip" is not based on !invariant.group.
132 ; CHECK: MemoryUse(liveOnEntry)
133 ; CHECK-NEXT: %v2 = load i32
134 %v2 = load i32, i32* %a32, align 4, !invariant.group !0
135 ; CHECK: 2 = MemoryDef(1)
136 ; CHECK-NEXT: store i32 1
137 store i32 1, i32* @g, align 4
139 ; CHECK: MemoryUse(2) {{.*}} clobbered by liveOnEntry
140 ; CHECK-NEXT: %v3 = load i32
141 %v3 = load i32, i32* %a32, align 4, !invariant.group !0
142 %add = add nsw i32 %v2, %v3
143 %add2 = add nsw i32 %add, %v
147 ; CHECK-LABEL: define {{.*}} @handleInvariantGroups(
148 define i32 @handleInvariantGroups(i32* %a) {
149 ; CHECK: 1 = MemoryDef(liveOnEntry)
150 ; CHECK-NEXT: store i32 0
151 store i32 0, i32* %a, align 4, !invariant.group !0
153 ; CHECK: 2 = MemoryDef(1)
154 ; CHECK-NEXT: store i32 1
155 store i32 1, i32* @g, align 4
156 %1 = bitcast i32* %a to i8*
157 ; CHECK: 3 = MemoryDef(2)
158 ; CHECK-NEXT: %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
159 %a8 = call i8* @llvm.launder.invariant.group.p0i8(i8* %1)
160 %a32 = bitcast i8* %a8 to i32*
162 ; CHECK: MemoryUse(2)
163 ; CHECK-NEXT: %2 = load i32
164 %2 = load i32, i32* %a32, align 4, !invariant.group !0
166 ; CHECK: 4 = MemoryDef(3)
167 ; CHECK-NEXT: store i32 2
168 store i32 2, i32* @g, align 4
170 ; CHECK: MemoryUse(4) {{.*}} clobbered by 2
171 ; CHECK-NEXT: %3 = load i32
172 %3 = load i32, i32* %a32, align 4, !invariant.group !0
173 %add = add nsw i32 %2, %3
177 ; CHECK-LABEL: define {{.*}} @loop(
178 define i32 @loop(i1 %a) {
180 %0 = alloca i32, align 4
181 ; CHECK: 1 = MemoryDef(liveOnEntry)
182 ; CHECK-NEXT: store i32 4
183 store i32 4, i32* %0, !invariant.group !0
184 ; CHECK: 2 = MemoryDef(1)
185 ; CHECK-NEXT: call void @clobber
186 call void @clobber(i32* %0)
187 br i1 %a, label %Loop.Body, label %Loop.End
190 ; CHECK: MemoryUse(2) {{.*}} clobbered by 1
191 ; CHECK-NEXT: %1 = load i32
192 %1 = load i32, i32* %0, !invariant.group !0
193 br i1 %a, label %Loop.End, label %Loop.Body
196 ; CHECK: MemoryUse(2) {{.*}} clobbered by 1
197 ; CHECK-NEXT: %2 = load
198 %2 = load i32, i32* %0, align 4, !invariant.group !0
199 br i1 %a, label %Ret, label %Loop.Body
205 ; CHECK-LABEL: define {{.*}} @loop2(
206 define i8 @loop2(i8* %p) {
208 ; CHECK: 1 = MemoryDef(liveOnEntry)
209 ; CHECK-NEXT: store i8
210 store i8 4, i8* %p, !invariant.group !0
211 ; CHECK: 2 = MemoryDef(1)
212 ; CHECK-NEXT: call void @clobber
213 call void @clobber8(i8* %p)
215 ; CHECK: 3 = MemoryDef(2)
216 ; CHECK-NEXT: %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
217 %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
218 br i1 undef, label %Loop.Body, label %Loop.End
221 ; CHECK: MemoryUse(6)
222 ; CHECK-NEXT: %0 = load i8
223 %0 = load i8, i8* %after, !invariant.group !0
225 ; CHECK: MemoryUse(6) {{.*}} clobbered by 1
226 ; CHECK-NEXT: %1 = load i8
227 %1 = load i8, i8* %p, !invariant.group !0
229 ; CHECK: 4 = MemoryDef(6)
230 store i8 4, i8* %after, !invariant.group !0
232 br i1 undef, label %Loop.End, label %Loop.Body
235 ; CHECK: MemoryUse(5)
236 ; CHECK-NEXT: %2 = load
237 %2 = load i8, i8* %after, align 4, !invariant.group !0
239 ; CHECK: MemoryUse(5) {{.*}} clobbered by 1
240 ; CHECK-NEXT: %3 = load
241 %3 = load i8, i8* %p, align 4, !invariant.group !0
242 br i1 undef, label %Ret, label %Loop.Body
249 ; CHECK-LABEL: define {{.*}} @loop3(
250 define i8 @loop3(i8* %p) {
252 ; CHECK: 1 = MemoryDef(liveOnEntry)
253 ; CHECK-NEXT: store i8
254 store i8 4, i8* %p, !invariant.group !0
255 ; CHECK: 2 = MemoryDef(1)
256 ; CHECK-NEXT: call void @clobber
257 call void @clobber8(i8* %p)
259 ; CHECK: 3 = MemoryDef(2)
260 ; CHECK-NEXT: %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
261 %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
262 br i1 undef, label %Loop.Body, label %Loop.End
265 ; CHECK: MemoryUse(8)
266 ; CHECK-NEXT: %0 = load i8
267 %0 = load i8, i8* %after, !invariant.group !0
269 ; CHECK: 4 = MemoryDef(8)
270 ; CHECK-NEXT: call void @clobber8
271 call void @clobber8(i8* %after)
273 ; CHECK: MemoryUse(4) {{.*}} clobbered by 8
274 ; CHECK-NEXT: %1 = load i8
275 %1 = load i8, i8* %after, !invariant.group !0
277 br i1 undef, label %Loop.next, label %Loop.Body
279 ; CHECK: 5 = MemoryDef(4)
280 ; CHECK-NEXT: call void @clobber8
281 call void @clobber8(i8* %after)
283 ; CHECK: MemoryUse(5) {{.*}} clobbered by 8
284 ; CHECK-NEXT: %2 = load i8
285 %2 = load i8, i8* %after, !invariant.group !0
287 br i1 undef, label %Loop.End, label %Loop.Body
290 ; CHECK: MemoryUse(7)
291 ; CHECK-NEXT: %3 = load
292 %3 = load i8, i8* %after, align 4, !invariant.group !0
294 ; CHECK: 6 = MemoryDef(7)
295 ; CHECK-NEXT: call void @clobber8
296 call void @clobber8(i8* %after)
298 ; CHECK: MemoryUse(6) {{.*}} clobbered by 7
299 ; CHECK-NEXT: %4 = load
300 %4 = load i8, i8* %after, align 4, !invariant.group !0
301 br i1 undef, label %Ret, label %Loop.Body
307 ; CHECK-LABEL: define {{.*}} @loop4(
308 define i8 @loop4(i8* %p) {
310 ; CHECK: 1 = MemoryDef(liveOnEntry)
311 ; CHECK-NEXT: store i8
312 store i8 4, i8* %p, !invariant.group !0
313 ; CHECK: 2 = MemoryDef(1)
314 ; CHECK-NEXT: call void @clobber
315 call void @clobber8(i8* %p)
316 ; CHECK: 3 = MemoryDef(2)
317 ; CHECK-NEXT: %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
318 %after = call i8* @llvm.launder.invariant.group.p0i8(i8* %p)
319 br i1 undef, label %Loop.Pre, label %Loop.End
322 ; CHECK: MemoryUse(2)
323 ; CHECK-NEXT: %0 = load i8
324 %0 = load i8, i8* %after, !invariant.group !0
327 ; CHECK: MemoryUse(6)
328 ; CHECK-NEXT: %1 = load i8
329 %1 = load i8, i8* %after, !invariant.group !0
331 ; CHECK: MemoryUse(6) {{.*}} clobbered by 1
332 ; CHECK-NEXT: %2 = load i8
333 %2 = load i8, i8* %p, !invariant.group !0
335 ; CHECK: 4 = MemoryDef(6)
336 store i8 4, i8* %after, !invariant.group !0
337 br i1 undef, label %Loop.End, label %Loop.Body
340 ; CHECK: MemoryUse(5)
341 ; CHECK-NEXT: %3 = load
342 %3 = load i8, i8* %after, align 4, !invariant.group !0
344 ; CHECK: MemoryUse(5) {{.*}} clobbered by 1
345 ; CHECK-NEXT: %4 = load
346 %4 = load i8, i8* %p, align 4, !invariant.group !0
347 br i1 undef, label %Ret, label %Loop.Body
353 ; In the future we would like to CSE barriers if there is no clobber between.
354 ; CHECK-LABEL: define {{.*}} @optimizable(
355 define i8 @optimizable() {
358 ; CHECK: 1 = MemoryDef(liveOnEntry)
359 ; CHECK-NEXT: store i8 42, i8* %ptr, align 1, !invariant.group !0
360 store i8 42, i8* %ptr, !invariant.group !0
361 ; CHECK: 2 = MemoryDef(1)
362 ; CHECK-NEXT: call i8* @llvm.launder.invariant.group
363 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
364 ; FIXME: This one could be CSEd.
365 ; CHECK: 3 = MemoryDef(2)
366 ; CHECK: call i8* @llvm.launder.invariant.group
367 %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
368 ; CHECK: 4 = MemoryDef(3)
369 ; CHECK-NEXT: call void @clobber8(i8* %ptr)
370 call void @clobber8(i8* %ptr)
371 ; CHECK: 5 = MemoryDef(4)
372 ; CHECK-NEXT: call void @use(i8* %ptr2)
373 call void @use(i8* %ptr2)
374 ; CHECK: 6 = MemoryDef(5)
375 ; CHECK-NEXT: call void @use(i8* %ptr3)
376 call void @use(i8* %ptr3)
377 ; CHECK: MemoryUse(6)
378 ; CHECK-NEXT: load i8, i8* %ptr3, {{.*}}!invariant.group
379 %v = load i8, i8* %ptr3, !invariant.group !0
384 ; CHECK-LABEL: define {{.*}} @unoptimizable2()
385 define i8 @unoptimizable2() {
387 ; CHECK: 1 = MemoryDef(liveOnEntry)
388 ; CHECK-NEXT: store i8 42, i8* %ptr, align 1, !invariant.group !0
389 store i8 42, i8* %ptr, !invariant.group !0
390 ; CHECK: 2 = MemoryDef(1)
391 ; CHECK-NEXT: call i8* @llvm.launder.invariant.group
392 %ptr2 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
393 ; CHECK: 3 = MemoryDef(2)
394 store i8 43, i8* %ptr
395 ; CHECK: 4 = MemoryDef(3)
396 ; CHECK-NEXT: call i8* @llvm.launder.invariant.group
397 %ptr3 = call i8* @llvm.launder.invariant.group.p0i8(i8* %ptr)
398 ; CHECK: 5 = MemoryDef(4)
399 ; CHECK-NEXT: call void @clobber8(i8* %ptr)
400 call void @clobber8(i8* %ptr)
401 ; CHECK: 6 = MemoryDef(5)
402 ; CHECK-NEXT: call void @use(i8* %ptr2)
403 call void @use(i8* %ptr2)
404 ; CHECK: 7 = MemoryDef(6)
405 ; CHECK-NEXT: call void @use(i8* %ptr3)
406 call void @use(i8* %ptr3)
407 ; CHECK: MemoryUse(7)
408 ; CHECK-NEXT: %v = load i8, i8* %ptr3, align 1, !invariant.group !0
409 %v = load i8, i8* %ptr3, !invariant.group !0
414 declare i8* @llvm.launder.invariant.group.p0i8(i8*)
415 declare void @clobber(i32*)
416 declare void @clobber8(i8*)
417 declare void @use(i8* readonly)