1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=memcpyopt -S %s -verify-memoryssa | FileCheck %s
4 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
6 @C = external constant [0 x i8]
8 define void @test_constant(i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) {
9 ; CHECK-LABEL: @test_constant(
10 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
11 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
12 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
13 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
14 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
15 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]]
16 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
17 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr @C, i64 [[SRC_SIZE]], i1 false)
18 ; CHECK-NEXT: ret void
20 %non.zero = icmp ne i64 %src_size, 0
21 call void @llvm.assume(i1 %non.zero)
22 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
23 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr @C, i64 %src_size, i1 false)
27 define void @test(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
29 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
30 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
31 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
32 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
33 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
34 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]]
35 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
36 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
37 ; CHECK-NEXT: ret void
39 %non.zero = icmp ne i64 %src_size, 0
40 call void @llvm.assume(i1 %non.zero)
41 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
42 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
46 define void @test_different_types_i32_i64(ptr noalias %dst, ptr %src, i32 %dst_size, i64 %src_size, i8 %c) {
47 ; CHECK-LABEL: @test_different_types_i32_i64(
48 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
49 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
50 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[DST_SIZE:%.*]] to i64
51 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i64 [[TMP1]], [[SRC_SIZE]]
52 ; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[TMP1]], [[SRC_SIZE]]
53 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP3]]
54 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]]
55 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 [[C:%.*]], i64 [[TMP4]], i1 false)
56 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
57 ; CHECK-NEXT: ret void
59 %non.zero = icmp ne i64 %src_size, 0
60 call void @llvm.assume(i1 %non.zero)
61 call void @llvm.memset.p0.i32(ptr %dst, i8 %c, i32 %dst_size, i1 false)
62 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
66 define void @test_different_types_i128_i32(ptr noalias %dst, ptr %src, i128 %dst_size, i32 %src_size, i8 %c) {
67 ; CHECK-LABEL: @test_different_types_i128_i32(
68 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i32 [[SRC_SIZE:%.*]], 0
69 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
70 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SRC_SIZE]] to i128
71 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i128 [[DST_SIZE:%.*]], [[TMP1]]
72 ; CHECK-NEXT: [[TMP3:%.*]] = sub i128 [[DST_SIZE]], [[TMP1]]
73 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i128 0, i128 [[TMP3]]
74 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[TMP1]]
75 ; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP5]], i8 [[C:%.*]], i128 [[TMP4]], i1 false)
76 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DST]], ptr [[SRC:%.*]], i32 [[SRC_SIZE]], i1 false)
77 ; CHECK-NEXT: ret void
79 %non.zero = icmp ne i32 %src_size, 0
80 call void @llvm.assume(i1 %non.zero)
81 call void @llvm.memset.p0.i128(ptr %dst, i8 %c, i128 %dst_size, i1 false)
82 call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %src_size, i1 false)
86 define void @test_different_types_i32_i128(ptr noalias %dst, ptr %src, i32 %dst_size, i128 %src_size, i8 %c) {
87 ; CHECK-LABEL: @test_different_types_i32_i128(
88 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i128 [[SRC_SIZE:%.*]], 0
89 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
90 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[DST_SIZE:%.*]] to i128
91 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i128 [[TMP1]], [[SRC_SIZE]]
92 ; CHECK-NEXT: [[TMP3:%.*]] = sub i128 [[TMP1]], [[SRC_SIZE]]
93 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i128 0, i128 [[TMP3]]
94 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i128 [[SRC_SIZE]]
95 ; CHECK-NEXT: call void @llvm.memset.p0.i128(ptr align 1 [[TMP5]], i8 [[C:%.*]], i128 [[TMP4]], i1 false)
96 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i128(ptr [[DST]], ptr [[SRC:%.*]], i128 [[SRC_SIZE]], i1 false)
97 ; CHECK-NEXT: ret void
99 %non.zero = icmp ne i128 %src_size, 0
100 call void @llvm.assume(i1 %non.zero)
101 call void @llvm.memset.p0.i32(ptr %dst, i8 %c, i32 %dst_size, i1 false)
102 call void @llvm.memcpy.p0.p0.i128(ptr %dst, ptr %src, i128 %src_size, i1 false)
106 define void @test_different_types_i64_i32(ptr noalias %dst, ptr %src, i64 %dst_size, i32 %src_size, i8 %c) {
107 ; CHECK-LABEL: @test_different_types_i64_i32(
108 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i32 [[SRC_SIZE:%.*]], 0
109 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
110 ; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[SRC_SIZE]] to i64
111 ; CHECK-NEXT: [[TMP2:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[TMP1]]
112 ; CHECK-NEXT: [[TMP3:%.*]] = sub i64 [[DST_SIZE]], [[TMP1]]
113 ; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP2]], i64 0, i64 [[TMP3]]
114 ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[TMP1]]
115 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP5]], i8 [[C:%.*]], i64 [[TMP4]], i1 false)
116 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr [[DST]], ptr [[SRC:%.*]], i32 [[SRC_SIZE]], i1 false)
117 ; CHECK-NEXT: ret void
119 %non.zero = icmp ne i32 %src_size, 0
120 call void @llvm.assume(i1 %non.zero)
121 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
122 call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %src_size, i1 false)
126 define void @test_align_same(ptr %src, ptr noalias %dst, i64 %dst_size) {
127 ; CHECK-LABEL: @test_align_same(
128 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 80
129 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 80
130 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
131 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80
132 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 [[TMP3]], i1 false)
133 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 80, i1 false)
134 ; CHECK-NEXT: ret void
136 call void @llvm.memset.p0.i64(ptr align 8 %dst, i8 0, i64 %dst_size, i1 false)
137 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 80, i1 false)
141 define void @test_align_min(ptr %src, ptr noalias %dst, i64 %dst_size) {
142 ; CHECK-LABEL: @test_align_min(
143 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 36
144 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 36
145 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
146 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 36
147 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[TMP4]], i8 0, i64 [[TMP3]], i1 false)
148 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 36, i1 false)
149 ; CHECK-NEXT: ret void
151 call void @llvm.memset.p0.i64(ptr align 8 %dst, i8 0, i64 %dst_size, i1 false)
152 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 36, i1 false)
156 define void @test_align_memcpy(ptr %src, ptr noalias %dst, i64 %dst_size) {
157 ; CHECK-LABEL: @test_align_memcpy(
158 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], 80
159 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], 80
160 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
161 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 80
162 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[TMP4]], i8 0, i64 [[TMP3]], i1 false)
163 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST]], ptr align 8 [[SRC:%.*]], i64 80, i1 false)
164 ; CHECK-NEXT: ret void
166 call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 %dst_size, i1 false)
167 call void @llvm.memcpy.p0.p0.i64(ptr align 8 %dst, ptr align 8 %src, i64 80, i1 false)
171 define void @test_non_i8_dst_type(ptr %src, i64 %src_size, ptr noalias %dst_pi64, i64 %dst_size, i8 %c) {
172 ; CHECK-LABEL: @test_non_i8_dst_type(
173 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
174 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
175 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
176 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
177 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
178 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST_PI64:%.*]], i64 [[SRC_SIZE]]
179 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
180 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST_PI64]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
181 ; CHECK-NEXT: ret void
183 %non.zero = icmp ne i64 %src_size, 0
184 call void @llvm.assume(i1 %non.zero)
185 call void @llvm.memset.p0.i64(ptr %dst_pi64, i8 %c, i64 %dst_size, i1 false)
186 call void @llvm.memcpy.p0.p0.i64(ptr %dst_pi64, ptr %src, i64 %src_size, i1 false)
190 define void @test_different_dst(ptr noalias %dst2, ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size) {
191 ; CHECK-LABEL: @test_different_dst(
192 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
193 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
194 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[DST:%.*]], i8 0, i64 [[DST_SIZE:%.*]], i1 false)
195 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST2:%.*]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
196 ; CHECK-NEXT: ret void
198 %non.zero = icmp ne i64 %src_size, 0
199 call void @llvm.assume(i1 %non.zero)
200 call void @llvm.memset.p0.i64(ptr %dst, i8 0, i64 %dst_size, i1 false)
201 call void @llvm.memcpy.p0.p0.i64(ptr %dst2, ptr %src, i64 %src_size, i1 false)
205 ; Make sure we also take into account dependencies on the destination.
207 define i8 @test_intermediate_read(ptr noalias %a, ptr %b) #0 {
208 ; CHECK-LABEL: @test_intermediate_read(
209 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[A:%.*]], i8 0, i64 64, i1 false)
210 ; CHECK-NEXT: [[R:%.*]] = load i8, ptr [[A]], align 1
211 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[B:%.*]], i64 24, i1 false)
212 ; CHECK-NEXT: ret i8 [[R]]
214 call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 64, i1 false)
216 call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 24, i1 false)
220 %struct = type { [8 x i8], [8 x i8] }
222 define void @test_intermediate_write(ptr %b) #0 {
223 ; CHECK-LABEL: @test_intermediate_write(
224 ; CHECK-NEXT: [[A:%.*]] = alloca [[STRUCT:%.*]], align 8
225 ; CHECK-NEXT: [[A1:%.*]] = getelementptr [[STRUCT]], ptr [[A]], i32 0, i32 1, i32 0
226 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[A]], i8 0, i64 16, i1 false)
227 ; CHECK-NEXT: store i8 1, ptr [[A1]], align 1
228 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[A]], ptr [[B:%.*]], i64 8, i1 false)
229 ; CHECK-NEXT: ret void
232 %a1 = getelementptr %struct, ptr %a, i32 0, i32 1, i32 0
233 call void @llvm.memset.p0.i64(ptr %a, i8 0, i64 16, i1 false)
235 call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 8, i1 false)
239 define void @test_throwing_call(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
240 ; CHECK-LABEL: @test_throwing_call(
241 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
242 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
243 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[DST:%.*]], i8 [[C:%.*]], i64 [[DST_SIZE:%.*]], i1 false)
244 ; CHECK-NEXT: call void @call() #[[ATTR3:[0-9]+]]
245 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
246 ; CHECK-NEXT: ret void
248 %non.zero = icmp ne i64 %src_size, 0
249 call void @llvm.assume(i1 %non.zero)
250 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
251 call void @call() readnone
252 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
256 define void @test_throwing_call_alloca(ptr %src, i64 %src_size, i64 %dst_size, i8 %c) {
257 ; CHECK-LABEL: @test_throwing_call_alloca(
258 ; CHECK-NEXT: [[DST:%.*]] = alloca i8, align 1
259 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
260 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
261 ; CHECK-NEXT: call void @call() #[[ATTR3]]
262 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
263 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
264 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
265 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST]], i64 [[SRC_SIZE]]
266 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
267 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
268 ; CHECK-NEXT: ret void
271 %non.zero = icmp ne i64 %src_size, 0
272 call void @llvm.assume(i1 %non.zero)
273 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
274 call void @call() readnone
275 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
279 ; %dst and %src in the memcpy may be equal, in which case shorting the memset
281 define void @test_missing_noalias(ptr %src, i64 %src_size, ptr %dst, i64 %dst_size, i8 %c) {
282 ; CHECK-LABEL: @test_missing_noalias(
283 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
284 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
285 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[DST:%.*]], i8 [[C:%.*]], i64 [[DST_SIZE:%.*]], i1 false)
286 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
287 ; CHECK-NEXT: ret void
289 %non.zero = icmp ne i64 %src_size, 0
290 call void @llvm.assume(i1 %non.zero)
291 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
292 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
296 define void @test_same_const_size(ptr noalias %src, ptr noalias %dst, i8 %c) {
297 ; CHECK-LABEL: @test_same_const_size(
298 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 16, i1 false)
299 ; CHECK-NEXT: ret void
301 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 16, i1 false)
302 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 16, i1 false)
306 define void @test_same_dynamic_size(ptr noalias %src, ptr noalias %dst, i64 %size, i8 %c) {
307 ; CHECK-LABEL: @test_same_dynamic_size(
308 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SIZE:%.*]], 0
309 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
310 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST:%.*]], ptr [[SRC:%.*]], i64 [[SIZE]], i1 false)
311 ; CHECK-NEXT: ret void
313 %non.zero = icmp ne i64 %size, 0
314 call void @llvm.assume(i1 %non.zero)
315 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %size, i1 false)
316 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %size, i1 false)
320 ; Destinations must alias, but are not trivially equal.
321 define void @test_must_alias_same_size(ptr noalias %src, ptr noalias %dst, i8 %c) {
322 ; CHECK-LABEL: @test_must_alias_same_size(
323 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 16
324 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[DST]], i64 16
325 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[GEP2]], ptr [[SRC:%.*]], i64 16, i1 false)
326 ; CHECK-NEXT: ret void
328 %gep1 = getelementptr i8, ptr %dst, i64 16
329 call void @llvm.memset.p0.i64(ptr %gep1, i8 %c, i64 16, i1 false)
330 %gep2 = getelementptr i8, ptr %dst, i64 16
331 call void @llvm.memcpy.p0.p0.i64(ptr %gep2, ptr %src, i64 16, i1 false)
335 define void @test_must_alias_different_size(ptr noalias %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
336 ; CHECK-LABEL: @test_must_alias_different_size(
337 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
338 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
339 ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 16
340 ; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i8, ptr [[DST]], i64 16
341 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
342 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
343 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
344 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[GEP2]], i64 [[SRC_SIZE]]
345 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
346 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[GEP2]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
347 ; CHECK-NEXT: ret void
349 %non.zero = icmp ne i64 %src_size, 0
350 call void @llvm.assume(i1 %non.zero)
351 %gep1 = getelementptr i8, ptr %dst, i64 16
352 call void @llvm.memset.p0.i64(ptr %gep1, i8 %c, i64 %dst_size, i1 false)
353 %gep2 = getelementptr i8, ptr %dst, i64 16
354 call void @llvm.memcpy.p0.p0.i64(ptr %gep2, ptr %src, i64 %src_size, i1 false)
358 define void @test_weird_element_type(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
359 ; CHECK-LABEL: @test_weird_element_type(
360 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
361 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
362 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
363 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
364 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
365 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[DST:%.*]], i64 [[SRC_SIZE]]
366 ; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
367 ; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[DST]], ptr [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
368 ; CHECK-NEXT: ret void
370 %non.zero = icmp ne i64 %src_size, 0
371 call void @llvm.assume(i1 %non.zero)
372 call void @llvm.memset.p0.i64(ptr %dst, i8 %c, i64 %dst_size, i1 false)
373 call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 %src_size, i1 false)
377 define void @test_addrspace(ptr addrspace(1) %src, i64 %src_size, ptr addrspace(1) noalias %dst, i64 %dst_size, i8 %c) {
378 ; CHECK-LABEL: @test_addrspace(
379 ; CHECK-NEXT: [[NON_ZERO:%.*]] = icmp ne i64 [[SRC_SIZE:%.*]], 0
380 ; CHECK-NEXT: call void @llvm.assume(i1 [[NON_ZERO]])
381 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ule i64 [[DST_SIZE:%.*]], [[SRC_SIZE]]
382 ; CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[DST_SIZE]], [[SRC_SIZE]]
383 ; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[TMP1]], i64 0, i64 [[TMP2]]
384 ; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr addrspace(1) [[DST:%.*]], i64 [[SRC_SIZE]]
385 ; CHECK-NEXT: call void @llvm.memset.p1.i64(ptr addrspace(1) align 1 [[TMP4]], i8 [[C:%.*]], i64 [[TMP3]], i1 false)
386 ; CHECK-NEXT: call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) [[DST]], ptr addrspace(1) [[SRC:%.*]], i64 [[SRC_SIZE]], i1 false)
387 ; CHECK-NEXT: ret void
389 %non.zero = icmp ne i64 %src_size, 0
390 call void @llvm.assume(i1 %non.zero)
391 call void @llvm.memset.p1.i64(ptr addrspace(1) %dst, i8 %c, i64 %dst_size, i1 false)
392 call void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) %dst, ptr addrspace(1) %src, i64 %src_size, i1 false)
396 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)
397 declare void @llvm.memcpy.p0.p0.i64(ptr nocapture, ptr nocapture readonly, i64, i1)
398 declare void @llvm.memset.p0.i32(ptr nocapture, i8, i32, i1)
399 declare void @llvm.memcpy.p0.p0.i32(ptr nocapture, ptr nocapture readonly, i32, i1)
400 declare void @llvm.memset.p0.i128(ptr nocapture, i8, i128, i1)
401 declare void @llvm.memcpy.p0.p0.i128(ptr nocapture, ptr nocapture readonly, i128, i1)
402 declare void @llvm.memset.p1.i64(ptr addrspace(1) nocapture, i8, i64, i1)
403 declare void @llvm.memcpy.p1.p1.i64(ptr addrspace(1) nocapture, ptr addrspace(1) nocapture readonly, i64, i1)