diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1150,7 +1150,12 @@ // mempcpy(x, y, n) -> llvm.memcpy(align 1 x, align 1 y, n), x + n CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), CI->getArgOperand(1), Align(1), N); + // Propagate attributes, but memcpy has no return value, so make sure that + // any return attributes are compliant. + // TODO: Attach return value attributes to the 1st operand to preserve them? NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, N); } diff --git a/llvm/test/Transforms/InstCombine/mempcpy.ll b/llvm/test/Transforms/InstCombine/mempcpy.ll --- a/llvm/test/Transforms/InstCombine/mempcpy.ll +++ b/llvm/test/Transforms/InstCombine/mempcpy.ll @@ -53,4 +53,15 @@ ret i8* %r } +; The original call may have attributes that can not propagate to memcpy. + +define i32 @PR48810() { +; CHECK-LABEL: @PR48810( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 undef, i8* align 536870912 null, i64 undef, i1 false) +; CHECK-NEXT: ret i32 undef +; + %r = call dereferenceable(1) i8* @mempcpy(i8* undef, i8* null, i64 undef) + ret i32 undef +} + declare i8* @mempcpy(i8*, i8* nocapture readonly, i64)