1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=dse -S | FileCheck %s
4 define void @write4to7(ptr nocapture %p) {
5 ; CHECK-LABEL: @write4to7(
7 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
8 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
9 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i1 false)
10 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1
11 ; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX1]], align 4
12 ; CHECK-NEXT: ret void
15 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
16 call void @llvm.memset.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 28, i1 false)
17 %arrayidx1 = getelementptr inbounds i32, ptr %p, i64 1
18 store i32 1, ptr %arrayidx1, align 4
22 define void @write4to7_weird_element_type(ptr nocapture %p) {
23 ; CHECK-LABEL: @write4to7_weird_element_type(
25 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
26 ; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
27 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP1]], i8 0, i64 24, i1 false)
28 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1
29 ; CHECK-NEXT: store i32 1, ptr [[ARRAYIDX1]], align 4
30 ; CHECK-NEXT: ret void
33 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
34 call void @llvm.memset.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 28, i1 false)
35 %arrayidx1 = getelementptr inbounds i32, ptr %p, i64 1
36 store i32 1, ptr %arrayidx1, align 4
40 define void @write4to7_addrspace(ptr addrspace(1) nocapture %p) {
41 ; CHECK-LABEL: @write4to7_addrspace(
43 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[P:%.*]], i64 1
44 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr addrspace(1) [[ARRAYIDX0]], i64 4
45 ; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 4 [[TMP0]], i8 0, i64 24, i1 false)
46 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[P]], i64 1
47 ; CHECK-NEXT: store i32 1, ptr addrspace(1) [[ARRAYIDX1]], align 4
48 ; CHECK-NEXT: ret void
51 %arrayidx0 = getelementptr inbounds i32, ptr addrspace(1) %p, i64 1
52 call void @llvm.memset.p1.i64(ptr addrspace(1) align 4 %arrayidx0, i8 0, i64 28, i1 false)
53 %arrayidx1 = getelementptr inbounds i32, ptr addrspace(1) %p, i64 1
54 store i32 1, ptr addrspace(1) %arrayidx1, align 4
58 define void @write4to7_atomic(ptr nocapture %p) {
59 ; CHECK-LABEL: @write4to7_atomic(
61 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
62 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
63 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i32 4)
64 ; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds i32, ptr [[P]], i64 1
65 ; CHECK-NEXT: store atomic i32 1, ptr [[ARRAYIDX1]] unordered, align 4
66 ; CHECK-NEXT: ret void
69 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
70 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 28, i32 4)
71 %arrayidx1 = getelementptr inbounds i32, ptr %p, i64 1
72 store atomic i32 1, ptr %arrayidx1 unordered, align 4
76 define void @write0to3(ptr nocapture %p) {
77 ; CHECK-LABEL: @write0to3(
79 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 4
80 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i1 false)
81 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
82 ; CHECK-NEXT: ret void
85 call void @llvm.memset.p0.i64(ptr align 4 %p, i8 0, i64 28, i1 false)
86 store i32 1, ptr %p, align 4
90 define void @write0to3_atomic(ptr nocapture %p) {
91 ; CHECK-LABEL: @write0to3_atomic(
93 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 4
94 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i32 4)
95 ; CHECK-NEXT: store atomic i32 1, ptr [[P]] unordered, align 4
96 ; CHECK-NEXT: ret void
99 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %p, i8 0, i64 28, i32 4)
100 store atomic i32 1, ptr %p unordered, align 4
104 ; Atomicity of the store is weaker from the memset
105 define void @write0to3_atomic_weaker(ptr nocapture %p) {
106 ; CHECK-LABEL: @write0to3_atomic_weaker(
108 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 4
109 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i32 4)
110 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
111 ; CHECK-NEXT: ret void
114 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %p, i8 0, i64 28, i32 4)
115 store i32 1, ptr %p, align 4
119 define void @write0to7(ptr nocapture %p) {
120 ; CHECK-LABEL: @write0to7(
122 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 8
123 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i1 false)
124 ; CHECK-NEXT: store i64 1, ptr [[P]], align 8
125 ; CHECK-NEXT: ret void
128 call void @llvm.memset.p0.i64(ptr align 4 %p, i8 0, i64 32, i1 false)
129 store i64 1, ptr %p, align 8
133 ; Changing the memset start and length is okay here because the
134 ; store is a multiple of the memset element size
135 define void @write0to7_atomic(ptr nocapture %p) {
136 ; CHECK-LABEL: @write0to7_atomic(
138 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 8
139 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i32 4)
140 ; CHECK-NEXT: store atomic i64 1, ptr [[P]] unordered, align 8
141 ; CHECK-NEXT: ret void
144 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %p, i8 0, i64 32, i32 4)
145 store atomic i64 1, ptr %p unordered, align 8
149 define void @write0to7_2(ptr nocapture %p) {
150 ; CHECK-LABEL: @write0to7_2(
152 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
153 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
154 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i1 false)
155 ; CHECK-NEXT: store i64 1, ptr [[P]], align 8
156 ; CHECK-NEXT: ret void
159 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
160 call void @llvm.memset.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 28, i1 false)
161 store i64 1, ptr %p, align 8
165 define void @write0to7_2_atomic(ptr nocapture %p) {
166 ; CHECK-LABEL: @write0to7_2_atomic(
168 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
169 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
170 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 24, i32 4)
171 ; CHECK-NEXT: store atomic i64 1, ptr [[P]] unordered, align 8
172 ; CHECK-NEXT: ret void
175 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
176 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 28, i32 4)
177 store atomic i64 1, ptr %p unordered, align 8
181 ; We do not trim the beginning of the eariler write if the alignment of the
182 ; start pointer is changed.
183 define void @dontwrite0to3_align8(ptr nocapture %p) {
184 ; CHECK-LABEL: @dontwrite0to3_align8(
186 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P:%.*]], i8 0, i64 32, i1 false)
187 ; CHECK-NEXT: store i32 1, ptr [[P]], align 4
188 ; CHECK-NEXT: ret void
191 call void @llvm.memset.p0.i64(ptr align 8 %p, i8 0, i64 32, i1 false)
192 store i32 1, ptr %p, align 4
196 define void @dontwrite0to3_align8_atomic(ptr nocapture %p) {
197 ; CHECK-LABEL: @dontwrite0to3_align8_atomic(
199 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 [[P:%.*]], i8 0, i64 32, i32 4)
200 ; CHECK-NEXT: store atomic i32 1, ptr [[P]] unordered, align 4
201 ; CHECK-NEXT: ret void
204 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 %p, i8 0, i64 32, i32 4)
205 store atomic i32 1, ptr %p unordered, align 4
209 define void @dontwrite0to1(ptr nocapture %p) {
210 ; CHECK-LABEL: @dontwrite0to1(
212 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[P:%.*]], i8 0, i64 32, i1 false)
213 ; CHECK-NEXT: store i16 1, ptr [[P]], align 4
214 ; CHECK-NEXT: ret void
217 call void @llvm.memset.p0.i64(ptr align 4 %p, i8 0, i64 32, i1 false)
218 store i16 1, ptr %p, align 4
222 define void @dontwrite0to1_atomic(ptr nocapture %p) {
223 ; CHECK-LABEL: @dontwrite0to1_atomic(
225 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[P:%.*]], i8 0, i64 32, i32 4)
226 ; CHECK-NEXT: store atomic i16 1, ptr [[P]] unordered, align 4
227 ; CHECK-NEXT: ret void
230 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %p, i8 0, i64 32, i32 4)
231 store atomic i16 1, ptr %p unordered, align 4
235 define void @write2to10(ptr nocapture %p) {
236 ; CHECK-LABEL: @write2to10(
238 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
239 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
240 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 28, i1 false)
241 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 1
242 ; CHECK-NEXT: store i64 1, ptr [[ARRAYIDX2]], align 8
243 ; CHECK-NEXT: ret void
246 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
247 call void @llvm.memset.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 32, i1 false)
248 %arrayidx2 = getelementptr inbounds i16, ptr %p, i64 1
249 store i64 1, ptr %arrayidx2, align 8
253 define void @write2to10_atomic(ptr nocapture %p) {
254 ; CHECK-LABEL: @write2to10_atomic(
256 ; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
257 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ARRAYIDX0]], i64 4
258 ; CHECK-NEXT: call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 28, i32 4)
259 ; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds i16, ptr [[P]], i64 1
260 ; CHECK-NEXT: store atomic i64 1, ptr [[ARRAYIDX2]] unordered, align 8
261 ; CHECK-NEXT: ret void
264 %arrayidx0 = getelementptr inbounds i32, ptr %p, i64 1
265 call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 4 %arrayidx0, i8 0, i64 32, i32 4)
266 %arrayidx2 = getelementptr inbounds i16, ptr %p, i64 1
267 store atomic i64 1, ptr %arrayidx2 unordered, align 8
271 define void @write8To15AndThen0To7(ptr nocapture %P) {
272 ; CHECK-LABEL: @write8To15AndThen0To7(
274 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 16
275 ; CHECK-NEXT: tail call void @llvm.memset.p0.i64(ptr align 8 [[TMP0]], i8 0, i64 16, i1 false)
276 ; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 1
277 ; CHECK-NEXT: store i64 1, ptr [[BASE64_1]], align 4
278 ; CHECK-NEXT: store i64 2, ptr [[P]], align 4
279 ; CHECK-NEXT: ret void
283 tail call void @llvm.memset.p0.i64(ptr align 8 %P, i8 0, i64 32, i1 false)
285 %base64_1 = getelementptr inbounds i64, ptr %P, i64 1
287 store i64 1, ptr %base64_1
292 define void @write8To15AndThen0To7_atomic(ptr nocapture %P) {
293 ; CHECK-LABEL: @write8To15AndThen0To7_atomic(
295 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 16
296 ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 [[TMP0]], i8 0, i64 16, i32 8)
297 ; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 1
298 ; CHECK-NEXT: store atomic i64 1, ptr [[BASE64_1]] unordered, align 8
299 ; CHECK-NEXT: store atomic i64 2, ptr [[P]] unordered, align 8
300 ; CHECK-NEXT: ret void
304 tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 %P, i8 0, i64 32, i32 8)
306 %base64_1 = getelementptr inbounds i64, ptr %P, i64 1
308 store atomic i64 1, ptr %base64_1 unordered, align 8
309 store atomic i64 2, ptr %P unordered, align 8
313 define void @write8To15AndThen0To7_atomic_weaker(ptr nocapture %P) {
314 ; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker(
316 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 16
317 ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 [[TMP0]], i8 0, i64 16, i32 8)
318 ; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 1
319 ; CHECK-NEXT: store atomic i64 1, ptr [[BASE64_1]] unordered, align 8
320 ; CHECK-NEXT: store i64 2, ptr [[P]], align 8
321 ; CHECK-NEXT: ret void
325 tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 %P, i8 0, i64 32, i32 8)
327 %base64_1 = getelementptr inbounds i64, ptr %P, i64 1
329 store atomic i64 1, ptr %base64_1 unordered, align 8
330 store i64 2, ptr %P, align 8
334 define void @write8To15AndThen0To7_atomic_weaker_2(ptr nocapture %P) {
335 ; CHECK-LABEL: @write8To15AndThen0To7_atomic_weaker_2(
337 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 16
338 ; CHECK-NEXT: tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 [[TMP0]], i8 0, i64 16, i32 8)
339 ; CHECK-NEXT: [[BASE64_1:%.*]] = getelementptr inbounds i64, ptr [[P]], i64 1
340 ; CHECK-NEXT: store i64 1, ptr [[BASE64_1]], align 8
341 ; CHECK-NEXT: store atomic i64 2, ptr [[P]] unordered, align 8
342 ; CHECK-NEXT: ret void
346 tail call void @llvm.memset.element.unordered.atomic.p0.i64(ptr align 8 %P, i8 0, i64 32, i32 8)
348 %base64_1 = getelementptr inbounds i64, ptr %P, i64 1
350 store i64 1, ptr %base64_1, align 8
351 store atomic i64 2, ptr %P unordered, align 8
355 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1) nounwind
356 declare void @llvm.memset.p1.i64(ptr addrspace(1) nocapture, i8, i64, i1) nounwind
357 declare void @llvm.memset.element.unordered.atomic.p0.i64(ptr nocapture, i8, i64, i32) nounwind
359 define void @ow_begin_align1(ptr nocapture %p) {
360 ; CHECK-LABEL: @ow_begin_align1(
362 ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 1
363 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 7
364 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP0]], i8 0, i64 25, i1 false)
365 ; CHECK-NEXT: store i64 1, ptr [[P]], align 1
366 ; CHECK-NEXT: ret void
369 %p1 = getelementptr inbounds i8, ptr %p, i64 1
370 call void @llvm.memset.p0.i64(ptr align 1 %p1, i8 0, i64 32, i1 false)
371 store i64 1, ptr %p, align 1
375 define void @ow_end_align4(ptr nocapture %p) {
376 ; CHECK-LABEL: @ow_end_align4(
378 ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 1
379 ; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[P1]], i64 4
380 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP0]], i8 0, i64 28, i1 false)
381 ; CHECK-NEXT: store i64 1, ptr [[P]], align 1
382 ; CHECK-NEXT: ret void
385 %p1 = getelementptr inbounds i8, ptr %p, i64 1
386 call void @llvm.memset.p0.i64(ptr align 4 %p1, i8 0, i64 32, i1 false)
387 store i64 1, ptr %p, align 1
391 define void @ow_end_align8(ptr nocapture %p) {
392 ; CHECK-LABEL: @ow_end_align8(
394 ; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 1
395 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[P1]], i8 0, i64 32, i1 false)
396 ; CHECK-NEXT: store i64 1, ptr [[P]], align 1
397 ; CHECK-NEXT: ret void
400 %p1 = getelementptr inbounds i8, ptr %p, i64 1
401 call void @llvm.memset.p0.i64(ptr align 8 %p1, i8 0, i64 32, i1 false)
402 store i64 1, ptr %p, align 1