[clangd] Re-land "support outgoing calls in call hierarchy" (#117673)
[llvm-project.git] / llvm / test / Transforms / MemCpyOpt / memset-memcpy-redundant-memset.ll
blob68356397423507e9e1e18615d13f6fb5ab6c38e0
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)
24   ret void
27 define void @test(ptr %src, i64 %src_size, ptr noalias %dst, i64 %dst_size, i8 %c) {
28 ; CHECK-LABEL: @test(
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)
43   ret void
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)
63   ret void
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)
83   ret void
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)
103   ret void
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)
123   ret void
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)
138   ret void
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)
153   ret void
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)
168   ret void
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)
187   ret void
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)
202   ret void
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)
215   %r = load i8, ptr %a
216   call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 24, i1 false)
217   ret i8 %r
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
231   %a = alloca %struct
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)
234   store i8 1, ptr %a1
235   call void @llvm.memcpy.p0.p0.i64(ptr %a, ptr %b, i64 8, i1 false)
236   ret void
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)
253   ret void
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
270   %dst = alloca i8
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)
276   ret void
279 ; %dst and %src in the memcpy may be equal, in which case shorting the memset
280 ; is not legal.
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)
293   ret void
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)
303   ret void
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)
317   ret void
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)
332   ret void
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)
355   ret void
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)
374   ret void
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)
393   ret void
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)
404 declare void @call()