Skip to content

Commit c68b560

Browse files
[DSE] Handle memmove with equal non-const sizes
Follow up for fhahn's D98284. Also fixes a case from PR47644. Reviewed By: fhahn Differential Revision: https://reviews.llvm.org/D98346
1 parent 077dc5c commit c68b560

File tree

2 files changed

+158
-16
lines changed

2 files changed

+158
-16
lines changed

llvm/lib/Transforms/Scalar/DeadStoreElimination.cpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -373,22 +373,14 @@ isOverwrite(const Instruction *LaterI, const Instruction *EarlierI,
373373
if (!Later.Size.isPrecise() || !Earlier.Size.isPrecise()) {
374374
// In case no constant size is known, try to an IR values for the number
375375
// of bytes written and check if they match.
376-
auto GetSizeFromInstr = [](const Instruction *I) -> Value * {
377-
if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) {
378-
switch (II->getIntrinsicID()) {
379-
default:
380-
return nullptr;
381-
case Intrinsic::memcpy:
382-
case Intrinsic::memset:
383-
return II->getArgOperand(2);
384-
}
385-
}
386-
return nullptr;
387-
};
388-
Value *LaterV = GetSizeFromInstr(LaterI);
389-
Value *EarlierV = GetSizeFromInstr(EarlierI);
390-
if (LaterV && LaterV == EarlierV && AA.isMustAlias(Earlier, Later))
391-
return OW_Complete;
376+
const auto *LaterMemI = dyn_cast<MemIntrinsic>(LaterI);
377+
const auto *EarlierMemI = dyn_cast<MemIntrinsic>(EarlierI);
378+
if (LaterMemI && EarlierMemI) {
379+
const Value *LaterV = LaterMemI->getLength();
380+
const Value *EarlierV = EarlierMemI->getLength();
381+
if (LaterV == EarlierV && AA.isMustAlias(Earlier, Later))
382+
return OW_Complete;
383+
}
392384

393385
// Masked stores have imprecise locations, but we can reason about them
394386
// to some extent.

llvm/test/Transforms/DeadStoreElimination/memory-intrinsics-sizes.ll

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,5 +199,155 @@ define void @memcpy_and_memset_different_size_values_3(i8* noalias %src, i8* noa
199199
ret void
200200
}
201201

202+
define void @memmove_equal_size_values(i8* noalias %src, i8* noalias %dst, i64 %len) {
203+
; CHECK-LABEL: @memmove_equal_size_values(
204+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN:%.*]], i1 false)
205+
; CHECK-NEXT: ret void
206+
;
207+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
208+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
209+
ret void
210+
}
211+
212+
define void @memmove_different_size_values_1(i8* noalias %src, i8* noalias %dst, i64 %len.1, i64 %len.2) {
213+
; CHECK-LABEL: @memmove_different_size_values_1(
214+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN_1:%.*]], i1 false)
215+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC]], i64 [[LEN_2:%.*]], i1 false)
216+
; CHECK-NEXT: ret void
217+
;
218+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.1, i1 false)
219+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.2, i1 false)
220+
ret void
221+
}
222+
223+
define void @memmove_different_size_values_2(i8* noalias %src, i8* noalias %dst, i64 %len) {
224+
; CHECK-LABEL: @memmove_different_size_values_2(
225+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN:%.*]], i1 false)
226+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC]], i64 100, i1 false)
227+
; CHECK-NEXT: ret void
228+
;
229+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
230+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 100, i1 false)
231+
ret void
232+
}
233+
234+
define void @memmove_different_size_values_3(i8* noalias %src, i8* noalias %dst, i64 %len) {
235+
; CHECK-LABEL: @memmove_different_size_values_3(
236+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 100, i1 false)
237+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC]], i64 [[LEN:%.*]], i1 false)
238+
; CHECK-NEXT: ret void
239+
;
240+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 100, i1 false)
241+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
242+
ret void
243+
}
244+
245+
define void @memset_and_memmove_equal_size_values(i8* noalias %src, i8* noalias %dst, i64 %len) {
246+
; CHECK-LABEL: @memset_and_memmove_equal_size_values(
247+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN:%.*]], i1 false)
248+
; CHECK-NEXT: ret void
249+
;
250+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len, i1 false)
251+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
252+
ret void
253+
}
254+
255+
define void @memset_and_memmove_different_size_values_1(i8* noalias %src, i8* noalias %dst, i64 %len.1, i64 %len.2) {
256+
; CHECK-LABEL: @memset_and_memmove_different_size_values_1(
257+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST:%.*]], i8 0, i64 [[LEN_1:%.*]], i1 false)
258+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC:%.*]], i64 [[LEN_2:%.*]], i1 false)
259+
; CHECK-NEXT: ret void
260+
;
261+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len.1, i1 false)
262+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.2, i1 false)
263+
ret void
264+
}
265+
266+
define void @memset_and_memmove_different_size_values_2(i8* noalias %src, i8* noalias %dst, i64 %len.1) {
267+
; CHECK-LABEL: @memset_and_memmove_different_size_values_2(
268+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST:%.*]], i8 0, i64 [[LEN_1:%.*]], i1 false)
269+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC:%.*]], i64 100, i1 false)
270+
; CHECK-NEXT: ret void
271+
;
272+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len.1, i1 false)
273+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 100, i1 false)
274+
ret void
275+
}
276+
277+
define void @memset_and_memmove_different_size_values_3(i8* noalias %src, i8* noalias %dst, i64 %len.1) {
278+
; CHECK-LABEL: @memset_and_memmove_different_size_values_3(
279+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST:%.*]], i8 0, i64 100, i1 false)
280+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST]], i8* [[SRC:%.*]], i64 [[LEN_1:%.*]], i1 false)
281+
; CHECK-NEXT: ret void
282+
;
283+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 100, i1 false)
284+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.1, i1 false)
285+
ret void
286+
}
287+
288+
define void @memmove_and_memset_equal_size_values(i8* noalias %src, i8* noalias %dst, i64 %len) {
289+
; CHECK-LABEL: @memmove_and_memset_equal_size_values(
290+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST:%.*]], i8 0, i64 [[LEN:%.*]], i1 false)
291+
; CHECK-NEXT: ret void
292+
;
293+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
294+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len, i1 false)
295+
ret void
296+
}
297+
298+
define void @memmove_and_memset_different_size_values_1(i8* noalias %src, i8* noalias %dst, i64 %len.1, i64 %len.2) {
299+
; CHECK-LABEL: @memmove_and_memset_different_size_values_1(
300+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN_1:%.*]], i1 false)
301+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST]], i8 0, i64 [[LEN_2:%.*]], i1 false)
302+
; CHECK-NEXT: ret void
303+
;
304+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.1, i1 false)
305+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len.2, i1 false)
306+
ret void
307+
}
308+
309+
define void @memmove_and_memset_different_size_values_2(i8* noalias %src, i8* noalias %dst, i64 %len.1) {
310+
; CHECK-LABEL: @memmove_and_memset_different_size_values_2(
311+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN_1:%.*]], i1 false)
312+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST]], i8 0, i64 100, i1 false)
313+
; CHECK-NEXT: ret void
314+
;
315+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len.1, i1 false)
316+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 100, i1 false)
317+
ret void
318+
}
319+
320+
define void @memmove_and_memset_different_size_values_3(i8* noalias %src, i8* noalias %dst, i64 %len.1) {
321+
; CHECK-LABEL: @memmove_and_memset_different_size_values_3(
322+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 100, i1 false)
323+
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST]], i8 0, i64 [[LEN_1:%.*]], i1 false)
324+
; CHECK-NEXT: ret void
325+
;
326+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 100, i1 false)
327+
call void @llvm.memset.p0i8.i64(i8* align 1 %dst, i8 0, i64 %len.1, i1 false)
328+
ret void
329+
}
330+
331+
define void @memmove_and_memcpy_equal_size_values(i8* noalias %src, i8* noalias %dst, i64 %len) {
332+
; CHECK-LABEL: @memmove_and_memcpy_equal_size_values(
333+
; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN:%.*]], i1 false)
334+
; CHECK-NEXT: ret void
335+
;
336+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
337+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
338+
ret void
339+
}
340+
341+
define void @memcpy_and_memmove_equal_size_values(i8* noalias %src, i8* noalias %dst, i64 %len) {
342+
; CHECK-LABEL: @memcpy_and_memmove_equal_size_values(
343+
; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* [[DST:%.*]], i8* [[SRC:%.*]], i64 [[LEN:%.*]], i1 false)
344+
; CHECK-NEXT: ret void
345+
;
346+
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
347+
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 %len, i1 false)
348+
ret void
349+
}
350+
202351
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg)
203352
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)
353+
declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1)

0 commit comments

Comments
 (0)