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 @@ -541,6 +541,8 @@ B.CreateMemCpy(Dst, Align(1), Src, Align(1), ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return Dst; } @@ -568,6 +570,8 @@ // copy for us. Make a memcpy to copy the nul byte with align = 1. CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), LenV); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return DstEnd; } @@ -627,6 +631,8 @@ CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), ConstantInt::get(DL.getIntPtrType(PT), Len)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return Dst; } @@ -1102,6 +1108,8 @@ CallInst *NewCI = B.CreateMemCpy(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), Size); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } @@ -1169,6 +1177,8 @@ CallInst *NewCI = B.CreateMemMove(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), Size); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } @@ -1229,6 +1239,8 @@ Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, Size, Align(1)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } @@ -3266,6 +3278,8 @@ B.CreateMemCpy(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), CI->getArgOperand(2)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } return nullptr; @@ -3278,6 +3292,8 @@ B.CreateMemMove(CI->getArgOperand(0), Align(1), CI->getArgOperand(1), Align(1), CI->getArgOperand(2)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } return nullptr; @@ -3292,6 +3308,8 @@ CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), Align(1)); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes(AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return CI->getArgOperand(0); } return nullptr; @@ -3305,6 +3323,9 @@ CI->getArgOperand(2), B, DL, TLI)) { CallInst *NewCI = cast(Call); NewCI->setAttributes(CI->getAttributes()); + NewCI->removeAttributes( + AttributeList::ReturnIndex, + AttributeFuncs::typeIncompatible(NewCI->getType())); return NewCI; } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/memcpy-1.ll b/llvm/test/Transforms/InstCombine/memcpy-1.ll --- a/llvm/test/Transforms/InstCombine/memcpy-1.ll +++ b/llvm/test/Transforms/InstCombine/memcpy-1.ll @@ -28,3 +28,12 @@ %ret = call i8* @memcpy(i8* %mem1, i8* %mem2, i32 %size) strictfp ret i8* %ret } + +define i8* @test_no_incompatible_attr(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 1 [[MEM1:%.*]], i8* align 1 [[MEM2:%.*]], i32 [[SIZE:%.*]], i1 false) +; CHECK-NEXT: ret i8* [[MEM1]] + + %ret = call dereferenceable(1) i8* @memcpy(i8* %mem1, i8* %mem2, i32 %size) + ret i8* %ret +} diff --git a/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll b/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll --- a/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memcpy_chk-1.ll @@ -74,4 +74,15 @@ ret i8* %ret } +define i8* @test_no_incompatible_attr(i8* %mem, i32 %val, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) +; + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + %ret = call dereferenceable(1) i8* @__memcpy_chk(i8* %dst, i8* %src, i64 1824, i64 1824) + ret i8* %ret +} + declare i8* @__memcpy_chk(i8*, i8*, i64, i64) diff --git a/llvm/test/Transforms/InstCombine/memmove-1.ll b/llvm/test/Transforms/InstCombine/memmove-1.ll --- a/llvm/test/Transforms/InstCombine/memmove-1.ll +++ b/llvm/test/Transforms/InstCombine/memmove-1.ll @@ -15,3 +15,11 @@ ret i8* %ret ; CHECK: ret i8* %mem1 } + +define i8* @test_no_incompatible_attr(i8* %mem1, i8* %mem2, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( + %ret = call dereferenceable(1) i8* @memmove(i8* %mem1, i8* %mem2, i32 %size) +; CHECK: call void @llvm.memmove + ret i8* %ret +; CHECK: ret i8* %mem1 +} diff --git a/llvm/test/Transforms/InstCombine/memmove_chk-1.ll b/llvm/test/Transforms/InstCombine/memmove_chk-1.ll --- a/llvm/test/Transforms/InstCombine/memmove_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memmove_chk-1.ll @@ -66,4 +66,16 @@ ret i8* %ret } +define i8* @test_no_incompatible_attr(i8* %mem, i32 %val, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memmove.p0i8.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T1* @t1 to i8*), i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T2* @t2 to i8*), i64 1824, i1 false) +; CHECK-NEXT: ret i8* bitcast (%struct.T1* @t1 to i8*) +; + %dst = bitcast %struct.T1* @t1 to i8* + %src = bitcast %struct.T2* @t2 to i8* + + %ret = call dereferenceable(1) i8* @__memmove_chk(i8* %dst, i8* %src, i64 1824, i64 1824) + ret i8* %ret +} + declare i8* @__memmove_chk(i8*, i8*, i64, i64) diff --git a/llvm/test/Transforms/InstCombine/memset-1.ll b/llvm/test/Transforms/InstCombine/memset-1.ll --- a/llvm/test/Transforms/InstCombine/memset-1.ll +++ b/llvm/test/Transforms/InstCombine/memset-1.ll @@ -198,6 +198,15 @@ ret i8* %memset } +define i8* @test_no_incompatible_attr(i8* %mem, i32 %val, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[VAL:%.*]] to i8 +; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* align 1 [[MEM:%.*]], i8 [[TMP1]], i32 [[SIZE:%.*]], i1 false) +; CHECK-NEXT: ret i8* [[MEM]] +; + %ret = call dereferenceable(1) i8* @memset(i8* %mem, i32 %val, i32 %size) + ret i8* %ret +} attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind } diff --git a/llvm/test/Transforms/InstCombine/memset_chk-1.ll b/llvm/test/Transforms/InstCombine/memset_chk-1.ll --- a/llvm/test/Transforms/InstCombine/memset_chk-1.ll +++ b/llvm/test/Transforms/InstCombine/memset_chk-1.ll @@ -141,6 +141,17 @@ } +define i8* @test_no_incompatible_attr(i8* %mem, i32 %val, i32 %size) { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull align 4 dereferenceable(1824) bitcast (%struct.T* @t to i8*), i8 0, i64 1824, i1 false) +; CHECK-NEXT: ret i8* bitcast (%struct.T* @t to i8*) +; + %dst = bitcast %struct.T* @t to i8* + + %ret = call dereferenceable(1) i8* @__memset_chk(i8* %dst, i32 0, i64 1824, i64 1824) + ret i8* %ret +} + declare noalias i8* @malloc(i64) #1 attributes #0 = { nounwind ssp uwtable } diff --git a/llvm/test/Transforms/InstCombine/stpcpy-1.ll b/llvm/test/Transforms/InstCombine/stpcpy-1.ll --- a/llvm/test/Transforms/InstCombine/stpcpy-1.ll +++ b/llvm/test/Transforms/InstCombine/stpcpy-1.ll @@ -62,3 +62,16 @@ %ret = call i8* @stpcpy(i8* %dst, i8* %src) ret i8* %ret } + +define i8* @test_no_incompatible_attr() { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret i8* getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 5) +; + + %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + + %ret = call dereferenceable(1) i8* @stpcpy(i8* %dst, i8* %src) + ret i8* %ret +} diff --git a/llvm/test/Transforms/InstCombine/strcpy-1.ll b/llvm/test/Transforms/InstCombine/strcpy-1.ll --- a/llvm/test/Transforms/InstCombine/strcpy-1.ll +++ b/llvm/test/Transforms/InstCombine/strcpy-1.ll @@ -62,3 +62,15 @@ %ret = call i8* @strcpy(i8* %dst, i8* %src) ret i8* %ret } + +define void @test_no_incompatible_attr() { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void + + %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + + call dereferenceable(1) i8* @strcpy(i8* %dst, i8* %src) + ret void +} diff --git a/llvm/test/Transforms/InstCombine/strncpy-1.ll b/llvm/test/Transforms/InstCombine/strncpy-1.ll --- a/llvm/test/Transforms/InstCombine/strncpy-1.ll +++ b/llvm/test/Transforms/InstCombine/strncpy-1.ll @@ -169,3 +169,15 @@ call i8* @strncpy(i8* %dst, i8* %src, i32 8) ret void } + +define void @test_no_incompatible_attr() { +; CHECK-LABEL: @test_no_incompatible_attr( +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([32 x i8], [32 x i8]* @a, i32 0, i32 0), i8* nonnull align 1 dereferenceable(6) getelementptr inbounds ([6 x i8], [6 x i8]* @hello, i32 0, i32 0), i32 6, i1 false) +; CHECK-NEXT: ret void +; + %dst = getelementptr [32 x i8], [32 x i8]* @a, i32 0, i32 0 + %src = getelementptr [6 x i8], [6 x i8]* @hello, i32 0, i32 0 + + call i8* @strncpy(i8* %dst, i8* %src, i32 6) + ret void +}