[sanitizer] Improve FreeBSD ASLR detection
[llvm-project.git] / llvm / test / Analysis / MemorySSA / invariant-groups.ll
blob9a4bbb5c859b5f73c89828d1a7a78cc372a099e9
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(
6 define i32 @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
20   ret i32 %1
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
38   ret i32 %1
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
58 ; invariant.group.
59 ; CHECK: MemoryUse(2)
60 ; CHECK-NEXT: %2 = load i32
61   %2 = load i32, i32* %a32, align 4, !invariant.group !0
62   ret i32 %2
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
79   ret void
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
96   ret void
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
115   ret i32 %2
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
144   ret i32 %add2
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
174   ret i32 %add
177 ; CHECK-LABEL: define {{.*}} @loop(
178 define i32 @loop(i1 %a) {
179 entry:
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
189 Loop.Body:
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
195 Loop.End:
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
201 Ret:
202   ret i32 %2
205 ; CHECK-LABEL: define {{.*}} @loop2(
206 define i8 @loop2(i8* %p) {
207 entry:
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
220 Loop.Body:
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
234 Loop.End:
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
244 Ret:
245   ret i8 %3
249 ; CHECK-LABEL: define {{.*}} @loop3(
250 define i8 @loop3(i8* %p) {
251 entry:
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
264 Loop.Body:
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
278 Loop.next:
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
289 Loop.End:
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
303 Ret:
304   ret i8 %3
307 ; CHECK-LABEL: define {{.*}} @loop4(
308 define i8 @loop4(i8* %p) {
309 entry:
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
321 Loop.Pre:
322 ; CHECK: MemoryUse(2)
323 ; CHECK-NEXT: %0 = load i8
324   %0 = load i8, i8* %after, !invariant.group !0
325   br label %Loop.Body
326 Loop.Body:
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
339 Loop.End:
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
349 Ret:
350   ret i8 %3
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() {
356 entry:
357   %ptr = alloca i8
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
381   ret i8 %v
384 ; CHECK-LABEL: define {{.*}} @unoptimizable2()
385 define i8 @unoptimizable2() {
386   %ptr = alloca i8
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
410   ret i8 %v
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)
419 !0 = !{!"group1"}