Files
clang-p2996/llvm/test/Transforms/MemCpyOpt/memcpy-zero-size.ll
Nikita Popov 71051deff2 [MemCpyOpt] Fix infinite loop in memset+memcpy fold (#98638)
For the case where the memcpy size is zero, this transform is a complex
no-op. This can lead to an infinite loop when the size is zero in a way
that BasicAA understands, because it can still understand that dst and
dst + src_size are MustAlias.

I've tried to mitigate this before using the isZeroSize() check, but we
can hit cases where InstSimplify doesn't understand that the size is
zero, but BasicAA does.

As such, this bites the bullet and adds an explicit isKnownNonZero()
check to guard against no-op transforms.

Fixes https://github.com/llvm/llvm-project/issues/98610.
2024-07-15 09:41:11 +02:00

52 lines
1.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -passes=memcpyopt < %s | FileCheck %s
declare void @llvm.memset.p0.i64(ptr, i8, i64, i1)
declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)
define void @zero_size(ptr %p, ptr %p2) {
; CHECK-LABEL: @zero_size(
; CHECK-NEXT: ret void
;
call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 0, i1 false)
ret void
}
; The memcpy size is zero in a way that is non-trivial, but understood by AA.
define void @pr54983(ptr %p, ptr noalias %p2) {
; CHECK-LABEL: @pr54983(
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 1, i1 false)
; CHECK-NEXT: [[SIZE:%.*]] = shl i64 0, 0
; CHECK-NEXT: ret void
;
call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 1, i1 false)
%size = shl i64 0, 0
call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %size, i1 false)
ret void
}
define void @pr64886(i64 %len, ptr noalias %p) {
; CHECK-LABEL: @pr64886(
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr inttoptr (i64 -1 to ptr), i8 0, i64 [[LEN:%.*]], i1 false)
; CHECK-NEXT: ret void
;
call void @llvm.memset.p0.i64(ptr inttoptr (i64 -1 to ptr), i8 0, i64 %len, i1 false)
call void @llvm.memcpy.p0.p0.i64(ptr inttoptr (i64 -1 to ptr), ptr %p, i64 poison, i1 false)
ret void
}
define void @pr98610(ptr %p, ptr noalias %p2) {
; CHECK-LABEL: @pr98610(
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr [[P:%.*]], i8 0, i64 1, i1 false)
; CHECK-NEXT: [[ZERO_EXT:%.*]] = zext i32 0 to i64
; CHECK-NEXT: [[MUL:%.*]] = mul i64 [[ZERO_EXT]], 1
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr [[P]], ptr [[P2:%.*]], i64 [[MUL]], i1 false)
; CHECK-NEXT: ret void
;
call void @llvm.memset.p0.i64(ptr %p, i8 0, i64 1, i1 false)
%zero.ext = zext i32 0 to i64
%mul = mul i64 %zero.ext, 1
call void @llvm.memcpy.p0.p0.i64(ptr %p, ptr %p2, i64 %mul, i1 false)
ret void
}