blob: 6e94ae178dbbfc5936decee9fb4ca01b16a59e3a [file] [log] [blame]
George Burgess IV82e355c2016-08-03 19:39:54 +00001; RUN: opt -basicaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s
2;
3; Currently, MemorySSA doesn't support invariant groups. So, we should ignore
4; invariant.group.barrier intrinsics entirely. We'll need to pay attention to
5; them when/if we decide to support invariant groups.
6
7@g = external global i32
8
9define i32 @foo(i32* %a) {
10; CHECK: 1 = MemoryDef(liveOnEntry)
11; CHECK-NEXT: store i32 0
Piotr Padlewskibff575f2017-01-21 21:56:56 +000012 store i32 0, i32* %a, align 4, !invariant.group !0
George Burgess IV82e355c2016-08-03 19:39:54 +000013
14; CHECK: 2 = MemoryDef(1)
15; CHECK-NEXT: store i32 1
16 store i32 1, i32* @g, align 4
17
18 %1 = bitcast i32* %a to i8*
19 %a8 = call i8* @llvm.invariant.group.barrier(i8* %1)
20 %a32 = bitcast i8* %a8 to i32*
21
Piotr Padlewskic050e6e2017-03-31 17:39:07 +000022; This have to be MemoryUse(2), because we can't skip the barrier based on
Piotr Padlewskibff575f2017-01-21 21:56:56 +000023; invariant.group.
George Burgess IV82e355c2016-08-03 19:39:54 +000024; CHECK: MemoryUse(2)
25; CHECK-NEXT: %2 = load i32
Piotr Padlewskibff575f2017-01-21 21:56:56 +000026 %2 = load i32, i32* %a32, align 4, !invariant.group !0
George Burgess IV82e355c2016-08-03 19:39:54 +000027 ret i32 %2
28}
29
Piotr Padlewskibff575f2017-01-21 21:56:56 +000030define i32 @skipBarrier(i32* %a) {
31; CHECK: 1 = MemoryDef(liveOnEntry)
32; CHECK-NEXT: store i32 0
33 store i32 0, i32* %a, align 4, !invariant.group !0
34
35 %1 = bitcast i32* %a to i8*
36 %a8 = call i8* @llvm.invariant.group.barrier(i8* %1)
37 %a32 = bitcast i8* %a8 to i32*
38
39; We can skip the barrier only if the "skip" is not based on !invariant.group.
40; CHECK: MemoryUse(1)
41; CHECK-NEXT: %2 = load i32
42 %2 = load i32, i32* %a32, align 4, !invariant.group !0
43 ret i32 %2
44}
45
46define i32 @skipBarrier2(i32* %a) {
47
48; CHECK: MemoryUse(liveOnEntry)
49; CHECK-NEXT: %v = load i32
50 %v = load i32, i32* %a, align 4, !invariant.group !0
51
52 %1 = bitcast i32* %a to i8*
53 %a8 = call i8* @llvm.invariant.group.barrier(i8* %1)
54 %a32 = bitcast i8* %a8 to i32*
55
56; We can skip the barrier only if the "skip" is not based on !invariant.group.
57; CHECK: MemoryUse(liveOnEntry)
58; CHECK-NEXT: %v2 = load i32
59 %v2 = load i32, i32* %a32, align 4, !invariant.group !0
60; CHECK: 1 = MemoryDef(liveOnEntry)
61; CHECK-NEXT: store i32 1
62 store i32 1, i32* @g, align 4
63
64; FIXME: based on invariant.group it should be MemoryUse(liveOnEntry)
65; CHECK: MemoryUse(1)
66; CHECK-NEXT: %v3 = load i32
67 %v3 = load i32, i32* %a32, align 4, !invariant.group !0
68 %add = add nsw i32 %v2, %v3
69 %add2 = add nsw i32 %add, %v
70 ret i32 %add2
71}
72
73define i32 @handleInvariantGroups(i32* %a) {
74; CHECK: 1 = MemoryDef(liveOnEntry)
75; CHECK-NEXT: store i32 0
76 store i32 0, i32* %a, align 4, !invariant.group !0
77
78; CHECK: 2 = MemoryDef(1)
79; CHECK-NEXT: store i32 1
80 store i32 1, i32* @g, align 4
81 %1 = bitcast i32* %a to i8*
82 %a8 = call i8* @llvm.invariant.group.barrier(i8* %1)
83 %a32 = bitcast i8* %a8 to i32*
84
85; CHECK: MemoryUse(2)
86; CHECK-NEXT: %2 = load i32
87 %2 = load i32, i32* %a32, align 4, !invariant.group !0
88
89; CHECK: 3 = MemoryDef(2)
90; CHECK-NEXT: store i32 2
91 store i32 2, i32* @g, align 4
92
93; FIXME: This can be changed to MemoryUse(2)
94; CHECK: MemoryUse(3)
95; CHECK-NEXT: %3 = load i32
96 %3 = load i32, i32* %a32, align 4, !invariant.group !0
97 %add = add nsw i32 %2, %3
98 ret i32 %add
99}
100
Piotr Padlewski4040d692017-01-23 16:38:10 +0000101define i32 @loop(i1 %a) {
102entry:
103 %0 = alloca i32, align 4
104; CHECK: 1 = MemoryDef(liveOnEntry)
105; CHECK-NEXT: store i32 4
106 store i32 4, i32* %0, !invariant.group !0
107; CHECK: 2 = MemoryDef(1)
108; CHECK-NEXT: call void @clobber
109 call void @clobber(i32* %0)
110 br i1 %a, label %Loop.Body, label %Loop.End
111
112Loop.Body:
113; FIXME: MemoryUse(1)
114; CHECK: MemoryUse(2)
115; CHECK-NEXT: %1 = load i32
116 %1 = load i32, i32* %0, !invariant.group !0
117 br i1 %a, label %Loop.End, label %Loop.Body
118
119Loop.End:
120; FIXME: MemoryUse(1)
121; CHECK: MemoryUse(2)
122; CHECK-NEXT: %2 = load
123 %2 = load i32, i32* %0, align 4, !invariant.group !0
124 br i1 %a, label %Ret, label %Loop.Body
125
126Ret:
127 ret i32 %2
128}
129
130define i8 @loop2(i8* %p) {
131entry:
132; CHECK: 1 = MemoryDef(liveOnEntry)
133; CHECK-NEXT: store i8
134 store i8 4, i8* %p, !invariant.group !0
135; CHECK: 2 = MemoryDef(1)
136; CHECK-NEXT: call void @clobber
137 call void @clobber8(i8* %p)
138 %after = call i8* @llvm.invariant.group.barrier(i8* %p)
139 br i1 undef, label %Loop.Body, label %Loop.End
140
141Loop.Body:
142; 4 = MemoryPhi({entry,2},{Loop.Body,3},{Loop.End,5})
143; CHECK: MemoryUse(4)
144; CHECK-NEXT: %0 = load i8
145 %0 = load i8, i8* %after, !invariant.group !0
146
147; FIXME: MemoryUse(1)
148; CHECK: MemoryUse(4)
149; CHECK-NEXT: %1 = load i8
150 %1 = load i8, i8* %p, !invariant.group !0
151
152; CHECK: 3 = MemoryDef(4)
153 store i8 4, i8* %after, !invariant.group !0
154
155 br i1 undef, label %Loop.End, label %Loop.Body
156
157Loop.End:
158; 5 = MemoryPhi({entry,2},{Loop.Body,3})
159; CHECK: MemoryUse(5)
160; CHECK-NEXT: %2 = load
161 %2 = load i8, i8* %after, align 4, !invariant.group !0
162
163; FIXME: MemoryUse(1)
164; CHECK: MemoryUse(5)
165; CHECK-NEXT: %3 = load
166 %3 = load i8, i8* %p, align 4, !invariant.group !0
167 br i1 undef, label %Ret, label %Loop.Body
168
169Ret:
170 ret i8 %3
171}
172
173
174define i8 @loop3(i8* %p) {
175entry:
176; CHECK: 1 = MemoryDef(liveOnEntry)
177; CHECK-NEXT: store i8
178 store i8 4, i8* %p, !invariant.group !0
179; CHECK: 2 = MemoryDef(1)
180; CHECK-NEXT: call void @clobber
181 call void @clobber8(i8* %p)
182 %after = call i8* @llvm.invariant.group.barrier(i8* %p)
183 br i1 undef, label %Loop.Body, label %Loop.End
184
185Loop.Body:
186; CHECK: 6 = MemoryPhi({entry,2},{Loop.Body,3},{Loop.next,4},{Loop.End,5})
187; CHECK: MemoryUse(6)
188; CHECK-NEXT: %0 = load i8
189 %0 = load i8, i8* %after, !invariant.group !0
190
191; CHECK: 3 = MemoryDef(6)
192; CHECK-NEXT: call void @clobber8
193 call void @clobber8(i8* %after)
194
195; FIXME: MemoryUse(6)
196; CHECK: MemoryUse(3)
197; CHECK-NEXT: %1 = load i8
198 %1 = load i8, i8* %after, !invariant.group !0
199
200 br i1 undef, label %Loop.next, label %Loop.Body
201Loop.next:
202; CHECK: 4 = MemoryDef(3)
203; CHECK-NEXT: call void @clobber8
204 call void @clobber8(i8* %after)
205
206; FIXME: MemoryUse(6)
207; CHECK: MemoryUse(4)
208; CHECK-NEXT: %2 = load i8
209 %2 = load i8, i8* %after, !invariant.group !0
210
211 br i1 undef, label %Loop.End, label %Loop.Body
212
213Loop.End:
214; CHECK: 7 = MemoryPhi({entry,2},{Loop.next,4})
215; CHECK: MemoryUse(7)
216; CHECK-NEXT: %3 = load
217 %3 = load i8, i8* %after, align 4, !invariant.group !0
218
219; CHECK: 5 = MemoryDef(7)
220; CHECK-NEXT: call void @clobber8
221 call void @clobber8(i8* %after)
222
223; FIXME: MemoryUse(7)
224; CHECK: MemoryUse(5)
225; CHECK-NEXT: %4 = load
226 %4 = load i8, i8* %after, align 4, !invariant.group !0
227 br i1 undef, label %Ret, label %Loop.Body
228
229Ret:
230 ret i8 %3
231}
232
233define i8 @loop4(i8* %p) {
234entry:
235; CHECK: 1 = MemoryDef(liveOnEntry)
236; CHECK-NEXT: store i8
237 store i8 4, i8* %p, !invariant.group !0
238; CHECK: 2 = MemoryDef(1)
239; CHECK-NEXT: call void @clobber
240 call void @clobber8(i8* %p)
241 %after = call i8* @llvm.invariant.group.barrier(i8* %p)
242 br i1 undef, label %Loop.Pre, label %Loop.End
243
244Loop.Pre:
245; CHECK: MemoryUse(2)
246; CHECK-NEXT: %0 = load i8
247 %0 = load i8, i8* %after, !invariant.group !0
248 br label %Loop.Body
249Loop.Body:
250; CHECK: 4 = MemoryPhi({Loop.Pre,2},{Loop.Body,3},{Loop.End,5})
251; CHECK-NEXT: MemoryUse(4)
252; CHECK-NEXT: %1 = load i8
253 %1 = load i8, i8* %after, !invariant.group !0
254
255; FIXME: MemoryUse(2)
256; CHECK: MemoryUse(4)
257; CHECK-NEXT: %2 = load i8
258 %2 = load i8, i8* %p, !invariant.group !0
259
260; CHECK: 3 = MemoryDef(4)
261 store i8 4, i8* %after, !invariant.group !0
262 br i1 undef, label %Loop.End, label %Loop.Body
263
264Loop.End:
265; CHECK: 5 = MemoryPhi({entry,2},{Loop.Body,3})
266; CHECK-NEXT: MemoryUse(5)
267; CHECK-NEXT: %3 = load
268 %3 = load i8, i8* %after, align 4, !invariant.group !0
269
270; FIXME: MemoryUse(2)
271; CHECK: MemoryUse(5)
272; CHECK-NEXT: %4 = load
273 %4 = load i8, i8* %p, align 4, !invariant.group !0
274 br i1 undef, label %Ret, label %Loop.Body
275
276Ret:
277 ret i8 %3
278}
279
George Burgess IV82e355c2016-08-03 19:39:54 +0000280declare i8* @llvm.invariant.group.barrier(i8*)
Piotr Padlewski4040d692017-01-23 16:38:10 +0000281declare void @clobber(i32*)
282declare void @clobber8(i8*)
283
George Burgess IV82e355c2016-08-03 19:39:54 +0000284
285!0 = !{!"group1"}