1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -basicaa -dse -S | FileCheck %s
3
4define void @write4to7(i32* nocapture %p) {
5; CHECK-LABEL: @write4to7(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
8; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
9; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
10; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
11; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
12; CHECK-NEXT:    store i32 1, i32* [[ARRAYIDX1]], align 4
13; CHECK-NEXT:    ret void
14;
15entry:
16  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
17  %p3 = bitcast i32* %arrayidx0 to i8*
18  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false)
19  %arrayidx1 = getelementptr inbounds i32, i32* %p, i64 1
20  store i32 1, i32* %arrayidx1, align 4
21  ret void
22}
23
24define void @write4to7_atomic(i32* nocapture %p) {
25; CHECK-LABEL: @write4to7_atomic(
26; CHECK-NEXT:  entry:
27; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
28; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
29; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4)
30; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 1
31; CHECK-NEXT:    store atomic i32 1, i32* [[ARRAYIDX1]] unordered, align 4
32; CHECK-NEXT:    ret void
33;
34entry:
35  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
36  %p3 = bitcast i32* %arrayidx0 to i8*
37  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4)
38  %arrayidx1 = getelementptr inbounds i32, i32* %p, i64 1
39  store atomic i32 1, i32* %arrayidx1 unordered, align 4
40  ret void
41}
42
43define void @write0to3(i32* nocapture %p) {
44; CHECK-LABEL: @write0to3(
45; CHECK-NEXT:  entry:
46; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
47; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
48; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
49; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
50; CHECK-NEXT:    ret void
51;
52entry:
53  %p3 = bitcast i32* %p to i8*
54  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false)
55  store i32 1, i32* %p, align 4
56  ret void
57}
58
59define void @write0to3_atomic(i32* nocapture %p) {
60; CHECK-LABEL: @write0to3_atomic(
61; CHECK-NEXT:  entry:
62; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
63; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4)
64; CHECK-NEXT:    store atomic i32 1, i32* [[P]] unordered, align 4
65; CHECK-NEXT:    ret void
66;
67entry:
68  %p3 = bitcast i32* %p to i8*
69  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4)
70  store atomic i32 1, i32* %p unordered, align 4
71  ret void
72}
73
74; Atomicity of the store is weaker from the memset
75define void @write0to3_atomic_weaker(i32* nocapture %p) {
76; CHECK-LABEL: @write0to3_atomic_weaker(
77; CHECK-NEXT:  entry:
78; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
79; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4)
80; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
81; CHECK-NEXT:    ret void
82;
83entry:
84  %p3 = bitcast i32* %p to i8*
85  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4)
86  store i32 1, i32* %p, align 4
87  ret void
88}
89
90define void @write0to7(i32* nocapture %p) {
91; CHECK-LABEL: @write0to7(
92; CHECK-NEXT:  entry:
93; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
94; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 8
95; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
96; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i64*
97; CHECK-NEXT:    store i64 1, i64* [[P4]], align 8
98; CHECK-NEXT:    ret void
99;
100entry:
101  %p3 = bitcast i32* %p to i8*
102  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false)
103  %p4 = bitcast i32* %p to i64*
104  store i64 1, i64* %p4, align 8
105  ret void
106}
107
108; Changing the memset start and length is okay here because the
109; store is a multiple of the memset element size
110define void @write0to7_atomic(i32* nocapture %p) {
111; CHECK-LABEL: @write0to7_atomic(
112; CHECK-NEXT:  entry:
113; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
114; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4)
115; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i64*
116; CHECK-NEXT:    store atomic i64 1, i64* [[P4]] unordered, align 8
117; CHECK-NEXT:    ret void
118;
119entry:
120  %p3 = bitcast i32* %p to i8*
121  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4)
122  %p4 = bitcast i32* %p to i64*
123  store atomic i64 1, i64* %p4 unordered, align 8
124  ret void
125}
126
127define void @write0to7_2(i32* nocapture %p) {
128; CHECK-LABEL: @write0to7_2(
129; CHECK-NEXT:  entry:
130; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
131; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
132; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[P3]], i64 4
133; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[TMP0]], i8 0, i64 24, i1 false)
134; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i64*
135; CHECK-NEXT:    store i64 1, i64* [[P4]], align 8
136; CHECK-NEXT:    ret void
137;
138entry:
139  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
140  %p3 = bitcast i32* %arrayidx0 to i8*
141  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i1 false)
142  %p4 = bitcast i32* %p to i64*
143  store i64 1, i64* %p4, align 8
144  ret void
145}
146
147define void @write0to7_2_atomic(i32* nocapture %p) {
148; CHECK-LABEL: @write0to7_2_atomic(
149; CHECK-NEXT:  entry:
150; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
151; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
152; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 28, i32 4)
153; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i64*
154; CHECK-NEXT:    store atomic i64 1, i64* [[P4]] unordered, align 8
155; CHECK-NEXT:    ret void
156;
157entry:
158  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
159  %p3 = bitcast i32* %arrayidx0 to i8*
160  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 28, i32 4)
161  %p4 = bitcast i32* %p to i64*
162  store atomic i64 1, i64* %p4 unordered, align 8
163  ret void
164}
165
166; We do not trim the beginning of the eariler write if the alignment of the
167; start pointer is changed.
168define void @dontwrite0to3_align8(i32* nocapture %p) {
169; CHECK-LABEL: @dontwrite0to3_align8(
170; CHECK-NEXT:  entry:
171; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
172; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 8 [[P3]], i8 0, i64 32, i1 false)
173; CHECK-NEXT:    store i32 1, i32* [[P]], align 4
174; CHECK-NEXT:    ret void
175;
176entry:
177  %p3 = bitcast i32* %p to i8*
178  call void @llvm.memset.p0i8.i64(i8* align 8 %p3, i8 0, i64 32, i1 false)
179  store i32 1, i32* %p, align 4
180  ret void
181}
182
183define void @dontwrite0to3_align8_atomic(i32* nocapture %p) {
184; CHECK-LABEL: @dontwrite0to3_align8_atomic(
185; CHECK-NEXT:  entry:
186; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
187; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[P3]], i8 0, i64 32, i32 4)
188; CHECK-NEXT:    store atomic i32 1, i32* [[P]] unordered, align 4
189; CHECK-NEXT:    ret void
190;
191entry:
192  %p3 = bitcast i32* %p to i8*
193  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %p3, i8 0, i64 32, i32 4)
194  store atomic i32 1, i32* %p unordered, align 4
195  ret void
196}
197
198define void @dontwrite0to1(i32* nocapture %p) {
199; CHECK-LABEL: @dontwrite0to1(
200; CHECK-NEXT:  entry:
201; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
202; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i1 false)
203; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i16*
204; CHECK-NEXT:    store i16 1, i16* [[P4]], align 4
205; CHECK-NEXT:    ret void
206;
207entry:
208  %p3 = bitcast i32* %p to i8*
209  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false)
210  %p4 = bitcast i32* %p to i16*
211  store i16 1, i16* %p4, align 4
212  ret void
213}
214
215define void @dontwrite0to1_atomic(i32* nocapture %p) {
216; CHECK-LABEL: @dontwrite0to1_atomic(
217; CHECK-NEXT:  entry:
218; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[P:%.*]] to i8*
219; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4)
220; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i16*
221; CHECK-NEXT:    store atomic i16 1, i16* [[P4]] unordered, align 4
222; CHECK-NEXT:    ret void
223;
224entry:
225  %p3 = bitcast i32* %p to i8*
226  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4)
227  %p4 = bitcast i32* %p to i16*
228  store atomic i16 1, i16* %p4 unordered, align 4
229  ret void
230}
231
232define void @dontwrite2to9(i32* nocapture %p) {
233; CHECK-LABEL: @dontwrite2to9(
234; CHECK-NEXT:  entry:
235; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
236; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
237; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i1 false)
238; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i16*
239; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, i16* [[P4]], i64 1
240; CHECK-NEXT:    [[P5:%.*]] = bitcast i16* [[ARRAYIDX2]] to i64*
241; CHECK-NEXT:    store i64 1, i64* [[P5]], align 8
242; CHECK-NEXT:    ret void
243;
244entry:
245  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
246  %p3 = bitcast i32* %arrayidx0 to i8*
247  call void @llvm.memset.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i1 false)
248  %p4 = bitcast i32* %p to i16*
249  %arrayidx2 = getelementptr inbounds i16, i16* %p4, i64 1
250  %p5 = bitcast i16* %arrayidx2 to i64*
251  store i64 1, i64* %p5, align 8
252  ret void
253}
254
255define void @dontwrite2to9_atomic(i32* nocapture %p) {
256; CHECK-LABEL: @dontwrite2to9_atomic(
257; CHECK-NEXT:  entry:
258; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
259; CHECK-NEXT:    [[P3:%.*]] = bitcast i32* [[ARRAYIDX0]] to i8*
260; CHECK-NEXT:    call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 [[P3]], i8 0, i64 32, i32 4)
261; CHECK-NEXT:    [[P4:%.*]] = bitcast i32* [[P]] to i16*
262; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, i16* [[P4]], i64 1
263; CHECK-NEXT:    [[P5:%.*]] = bitcast i16* [[ARRAYIDX2]] to i64*
264; CHECK-NEXT:    store atomic i64 1, i64* [[P5]] unordered, align 8
265; CHECK-NEXT:    ret void
266;
267entry:
268  %arrayidx0 = getelementptr inbounds i32, i32* %p, i64 1
269  %p3 = bitcast i32* %arrayidx0 to i8*
270  call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 4 %p3, i8 0, i64 32, i32 4)
271  %p4 = bitcast i32* %p to i16*
272  %arrayidx2 = getelementptr inbounds i16, i16* %p4, i64 1
273  %p5 = bitcast i16* %arrayidx2 to i64*
274  store atomic i64 1, i64* %p5 unordered, align 8
275  ret void
276}
277
278define void @write8To15AndThen0To7(i64* nocapture %P) {
279; CHECK-LABEL: @write8To15AndThen0To7(
280; CHECK-NEXT:  entry:
281; CHECK-NEXT:    [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8*
282; CHECK-NEXT:    [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0
283; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[MYBASE0]], i64 16
284; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* align 8 [[TMP0]], i8 0, i64 16, i1 false)
285; CHECK-NEXT:    [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0
286; CHECK-NEXT:    [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1
287; CHECK-NEXT:    store i64 1, i64* [[BASE64_1]]
288; CHECK-NEXT:    store i64 2, i64* [[BASE64_0]]
289; CHECK-NEXT:    ret void
290;
291entry:
292
293  %base0 = bitcast i64* %P to i8*
294  %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0
295  tail call void @llvm.memset.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i1 false)
296
297  %base64_0 = getelementptr inbounds i64, i64* %P, i64 0
298  %base64_1 = getelementptr inbounds i64, i64* %P, i64 1
299
300  store i64 1, i64* %base64_1
301  store i64 2, i64* %base64_0
302  ret void
303}
304
305define void @write8To15AndThen0To7_atomic(i64* nocapture %P) {
306; CHECK-LABEL: @write8To15AndThen0To7_atomic(
307; CHECK-NEXT:  entry:
308; CHECK-NEXT:    [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8*
309; CHECK-NEXT:    [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0
310; CHECK-NEXT:    tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8)
311; CHECK-NEXT:    [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0
312; CHECK-NEXT:    [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1
313; CHECK-NEXT:    store atomic i64 1, i64* [[BASE64_1]] unordered, align 8
314; CHECK-NEXT:    store atomic i64 2, i64* [[BASE64_0]] unordered, align 8
315; CHECK-NEXT:    ret void
316;
317entry:
318
319  %base0 = bitcast i64* %P to i8*
320  %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0
321  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8)
322
323  %base64_0 = getelementptr inbounds i64, i64* %P, i64 0
324  %base64_1 = getelementptr inbounds i64, i64* %P, i64 1
325
326  store atomic i64 1, i64* %base64_1 unordered, align 8
327  store atomic i64 2, i64* %base64_0 unordered, align 8
328  ret void
329}
330
331define void @write8To15AndThen0To7_atomic_weaker(i64* nocapture %P) {
332; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker(
333; CHECK-NEXT:  entry:
334; CHECK-NEXT:    [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8*
335; CHECK-NEXT:    [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0
336; CHECK-NEXT:    tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8)
337; CHECK-NEXT:    [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0
338; CHECK-NEXT:    [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1
339; CHECK-NEXT:    store atomic i64 1, i64* [[BASE64_1]] unordered, align 8
340; CHECK-NEXT:    store i64 2, i64* [[BASE64_0]], align 8
341; CHECK-NEXT:    ret void
342;
343entry:
344
345  %base0 = bitcast i64* %P to i8*
346  %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0
347  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8)
348
349  %base64_0 = getelementptr inbounds i64, i64* %P, i64 0
350  %base64_1 = getelementptr inbounds i64, i64* %P, i64 1
351
352  store atomic i64 1, i64* %base64_1 unordered, align 8
353  store i64 2, i64* %base64_0, align 8
354  ret void
355}
356
357define void @write8To15AndThen0To7_atomic_weaker_2(i64* nocapture %P) {
358; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker_2(
359; CHECK-NEXT:  entry:
360; CHECK-NEXT:    [[BASE0:%.*]] = bitcast i64* [[P:%.*]] to i8*
361; CHECK-NEXT:    [[MYBASE0:%.*]] = getelementptr inbounds i8, i8* [[BASE0]], i64 0
362; CHECK-NEXT:    tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 [[MYBASE0]], i8 0, i64 32, i32 8)
363; CHECK-NEXT:    [[BASE64_0:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 0
364; CHECK-NEXT:    [[BASE64_1:%.*]] = getelementptr inbounds i64, i64* [[P]], i64 1
365; CHECK-NEXT:    store i64 1, i64* [[BASE64_1]], align 8
366; CHECK-NEXT:    store atomic i64 2, i64* [[BASE64_0]] unordered, align 8
367; CHECK-NEXT:    ret void
368;
369entry:
370
371  %base0 = bitcast i64* %P to i8*
372  %mybase0 = getelementptr inbounds i8, i8* %base0, i64 0
373  tail call void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* align 8 %mybase0, i8 0, i64 32, i32 8)
374
375  %base64_0 = getelementptr inbounds i64, i64* %P, i64 0
376  %base64_1 = getelementptr inbounds i64, i64* %P, i64 1
377
378  store i64 1, i64* %base64_1, align 8
379  store atomic i64 2, i64* %base64_0 unordered, align 8
380  ret void
381}
382
383declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i1) nounwind
384declare void @llvm.memset.element.unordered.atomic.p0i8.i64(i8* nocapture, i8, i64, i32) nounwind
385
386