Skip to content

SimplifyLibCalls: Use the correct address space when computing integer widths. #118586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 44 additions & 45 deletions llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,9 +397,7 @@ Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,

// We have enough information to now generate the memcpy call to do the
// concatenation for us. Make a memcpy to copy the nul byte with align = 1.
B.CreateMemCpy(
CpyDst, Align(1), Src, Align(1),
ConstantInt::get(DL.getIntPtrType(Src->getContext()), Len + 1));
B.CreateMemCpy(CpyDst, Align(1), Src, Align(1), Len + 1);
return Dst;
}

Expand Down Expand Up @@ -590,26 +588,35 @@ Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilderBase &B) {
if (Len1 && Len2) {
return copyFlags(
*CI, emitMemCmp(Str1P, Str2P,
ConstantInt::get(DL.getIntPtrType(CI->getContext()),
std::min(Len1, Len2)),
ConstantInt::get(
DL.getIntPtrType(
CI->getContext(),
Str1P->getType()->getPointerAddressSpace()),
std::min(Len1, Len2)),
Comment on lines +591 to +595
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the memcmp case should probably have a similar wrapper

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going to change this, please change it to use the correct value -- which is TLI::getSizeTSize().

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, TLI::getSizeTSize() contains a nice comment explaining that it always uses addrspace(0), and noting that maybe it should consider alternatives, which is exactly the goal here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a few alternatives in here, none of them great:

  • We can use the current state of this patch, which will have every target always use i64. As efriedma points out, this will probably work out because of backend legalization.
  • We can thread TLI into IRBuilder::CreateMemCpy so that it can pick the right size. This requires updating a number of other passes throughout the tree, many of which don't depends on TargetLibraryInfo today.
  • Same as above, but we add it in parallel to the existing overloads so that we can migrate users gradually.
  • Build the types in SimplifyLibCalls as in the original version of this diff. Do some local cleanup to make it more readable per arsenm's feedback.

Thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason getSizeTSize() unconditionally queries addrspace(0) is just that there aren't any in-tree targets where it needs to return anything else. Fixes welcome.

Passing in a integer to emitMemCmp where the size isn't getSizeTSize() just miscompiles, as far as I know. (CreateMemCpy works fine in any case because it's an intrinsic.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason getSizeTSize() unconditionally queries addrspace(0) is just that there aren't any in-tree targets where it needs to return anything else. Fixes welcome.

Honestly, I don't think fixing getSizeTSize() makes sense. It's just a wrapper around DataLayout::getPointerSizeInBits, which is already more widely accessible throughout the middle-end than TargetLibraryInfo is.

If we really want the convenience name, then I think we should move getSizeTSize to DataLayout, and add an addrspace argument such that it is a pure wrapper around getPointerSizeInBits.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getSizeTSize() is supposed to be the bitwidth of the type size_t. There's only one size_t. This is useful because we're talking about C library functions, which are defined in terms of size_t.

If you want to query information about a specific address-space, we have appropriate datalayout APIs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be amenable to moving getSizeTSize() onto DataLayout? That would make it much easier to update all callers of CreateMemCpy.

I'll look at ensuring getSizeTSize() is correct for CHERI targets in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think getSizeTSize belongs on the data layout. It's a property related to the C library, rather than the target itself.

For CHERI's purposes, shouldn't it be sufficient to consistently make use of getSizeTSize() in this file and patch getSizeTSize() to return the correct value? Maybe just making the default value be the index type size instead of the pointer type size would be sufficient?

The BuildLibCalls code itself already uses the correct types, we're just not passing in matching types here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For CHERI's purposes, shouldn't it be sufficient to consistently make use of getSizeTSize() in this file and patch getSizeTSize() to return the correct value? Maybe just making the default value be the index type size instead of the pointer type size would be sufficient?

I've split such a change into #118747
There seems to be at least one test that concretely tests for the opposite behavior today, so we'll need to sort that out. If we can make that change, then most of the changes in this PR become irrelevant.

B, DL, TLI));
}

// strcmp to memcmp
if (!HasStr1 && HasStr2) {
if (canTransformToMemCmp(CI, Str1P, Len2, DL))
return copyFlags(
*CI,
emitMemCmp(Str1P, Str2P,
ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2),
B, DL, TLI));
*CI, emitMemCmp(Str1P, Str2P,
ConstantInt::get(
DL.getIntPtrType(
CI->getContext(),
Str1P->getType()->getPointerAddressSpace()),
Len2),
B, DL, TLI));
} else if (HasStr1 && !HasStr2) {
if (canTransformToMemCmp(CI, Str2P, Len1, DL))
return copyFlags(
*CI,
emitMemCmp(Str1P, Str2P,
ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1),
B, DL, TLI));
*CI, emitMemCmp(Str1P, Str2P,
ConstantInt::get(
DL.getIntPtrType(
CI->getContext(),
Str1P->getType()->getPointerAddressSpace()),
Len1),
B, DL, TLI));
}

annotateNonNullNoUndefBasedOnAccess(CI, {0, 1});
Expand Down Expand Up @@ -677,18 +684,24 @@ Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilderBase &B) {
Len2 = std::min(Len2, Length);
if (canTransformToMemCmp(CI, Str1P, Len2, DL))
return copyFlags(
*CI,
emitMemCmp(Str1P, Str2P,
ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2),
B, DL, TLI));
*CI, emitMemCmp(Str1P, Str2P,
ConstantInt::get(
DL.getIntPtrType(
CI->getContext(),
Str1P->getType()->getPointerAddressSpace()),
Len2),
B, DL, TLI));
} else if (HasStr1 && !HasStr2) {
Len1 = std::min(Len1, Length);
if (canTransformToMemCmp(CI, Str2P, Len1, DL))
return copyFlags(
*CI,
emitMemCmp(Str1P, Str2P,
ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1),
B, DL, TLI));
*CI, emitMemCmp(Str1P, Str2P,
ConstantInt::get(
DL.getIntPtrType(
CI->getContext(),
Str1P->getType()->getPointerAddressSpace()),
Len1),
B, DL, TLI));
}

return nullptr;
Expand Down Expand Up @@ -722,9 +735,7 @@ Value *LibCallSimplifier::optimizeStrCpy(CallInst *CI, IRBuilderBase &B) {

// We have enough information to now generate the memcpy call to do the
// copy for us. Make a memcpy to copy the nul byte with align = 1.
CallInst *NewCI =
B.CreateMemCpy(Dst, Align(1), Src, Align(1),
ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len));
CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), Len);
mergeAttributesAndFlags(NewCI, *CI);
return Dst;
}
Expand Down Expand Up @@ -819,13 +830,10 @@ Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) {
return ConstantInt::get(CI->getType(), 0);
}

Function *Callee = CI->getCalledFunction();
Type *PT = Callee->getFunctionType()->getParamType(0);
// Transform strlcpy(D, S, N) to memcpy(D, S, N') where N' is the lower
// bound on strlen(S) + 1 and N, optionally followed by a nul store to
// D[N' - 1] if necessary.
CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),
ConstantInt::get(DL.getIntPtrType(PT), NBytes));
CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), NBytes);
mergeAttributesAndFlags(NewCI, *CI);

if (!NulTerm) {
Expand All @@ -844,7 +852,6 @@ Value *LibCallSimplifier::optimizeStrLCpy(CallInst *CI, IRBuilderBase &B) {
// otherwise.
Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd,
IRBuilderBase &B) {
Function *Callee = CI->getCalledFunction();
Value *Dst = CI->getArgOperand(0);
Value *Src = CI->getArgOperand(1);
Value *Size = CI->getArgOperand(2);
Expand Down Expand Up @@ -921,11 +928,9 @@ Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd,
/*M=*/nullptr, /*AddNull=*/false);
}

Type *PT = Callee->getFunctionType()->getParamType(0);
// st{p,r}ncpy(D, S, N) -> memcpy(align 1 D, align 1 S, N) when both
// S and N are constant.
CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),
ConstantInt::get(DL.getIntPtrType(PT), N));
CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), N);
mergeAttributesAndFlags(NewCI, *CI);
if (!RetEnd)
return Dst;
Expand Down Expand Up @@ -3357,7 +3362,9 @@ Value *LibCallSimplifier::optimizePrintFString(CallInst *CI, IRBuilderBase &B) {
// Create a string literal with no \n on it. We expect the constant merge
// pass to be run after this pass, to merge duplicate strings.
FormatStr = FormatStr.drop_back();
Value *GV = B.CreateGlobalString(FormatStr, "str");
Value *GV = B.CreateGlobalString(
FormatStr, "str",
CI->getArgOperand(0)->getType()->getPointerAddressSpace());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're going to touch CreateGlobalString, please fix all the calls in this file at the same time.

On targets with multiple address-spaces, is it actually legal to create a global like this? I thought the usual convention was to create a global in some specific address-space, then addrspacecast it to the correct address-space.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally should try to use a context address space. For a newly synthesized global, there's DL.getDefaultGlobalsAddressSpace

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this specific line we're replacing one global string with another, so it makes sense to use the original address space. I'll look into other uses within this file.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getConstantStringInfo looks through addrspacecasts, so CI->getArgOperand(0)->getType()->getPointerAddressSpace() isn't necessarily the "original" address-space.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, let's just use the default globals address space. I'm going to split this component into a separate PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split off into #118729

Writing the test for this exposed more places where we were failing to propagate address spaces correctly, which are addressed in that PR as well.

return copyFlags(*CI, emitPutS(GV, B, TLI));
}

Expand Down Expand Up @@ -3432,10 +3439,8 @@ Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,
return nullptr; // we found a format specifier, bail out.

// sprintf(str, fmt) -> llvm.memcpy(align 1 str, align 1 fmt, strlen(fmt)+1)
B.CreateMemCpy(
Dest, Align(1), CI->getArgOperand(1), Align(1),
ConstantInt::get(DL.getIntPtrType(CI->getContext()),
FormatStr.size() + 1)); // Copy the null byte.
B.CreateMemCpy(Dest, Align(1), CI->getArgOperand(1), Align(1),
FormatStr.size() + 1); // Copy the null byte.
return ConstantInt::get(CI->getType(), FormatStr.size());
}

Expand Down Expand Up @@ -3470,9 +3475,7 @@ Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,

uint64_t SrcLen = GetStringLength(CI->getArgOperand(2));
if (SrcLen) {
B.CreateMemCpy(
Dest, Align(1), CI->getArgOperand(2), Align(1),
ConstantInt::get(DL.getIntPtrType(CI->getContext()), SrcLen));
B.CreateMemCpy(Dest, Align(1), CI->getArgOperand(2), Align(1), SrcLen);
// Returns total number of characters written without null-character.
return ConstantInt::get(CI->getType(), SrcLen - 1);
} else if (Value *V = emitStpCpy(Dest, CI->getArgOperand(2), B, TLI)) {
Expand Down Expand Up @@ -3570,11 +3573,7 @@ Value *LibCallSimplifier::emitSnPrintfMemCpy(CallInst *CI, Value *StrArg,
Value *DstArg = CI->getArgOperand(0);
if (NCopy && StrArg)
// Transform the call to lvm.memcpy(dst, fmt, N).
copyFlags(
*CI,
B.CreateMemCpy(
DstArg, Align(1), StrArg, Align(1),
ConstantInt::get(DL.getIntPtrType(CI->getContext()), NCopy)));
copyFlags(*CI, B.CreateMemCpy(DstArg, Align(1), StrArg, Align(1), NCopy));

if (N > Str.size())
// Return early when the whole format string, including the final nul,
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/ARM/strcpy.ll
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ define arm_aapcscc void @test_simplify1() {


call arm_aapcscc ptr @strcpy(ptr @a, ptr @hello)
; CHECK: @llvm.memcpy.p0.p0.i32
; CHECK: @llvm.memcpy.p0.p0.i64
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by these changes -- this test uses a p:32:32 data layout, so wasn't the previous i32 overload the correct one?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CreateMemCpy overload in question just calls getInt64().

I'm not sure it's much of a practical issue: backend legalization will truncate the integer to the appropriate size. But maybe we should canonicalize somewhere.

ret void
}

Expand All @@ -43,7 +43,7 @@ define arm_aapcs_vfpcc void @test_simplify1_vfp() {


call arm_aapcs_vfpcc ptr @strcpy(ptr @a, ptr @hello)
; CHECK: @llvm.memcpy.p0.p0.i32
; CHECK: @llvm.memcpy.p0.p0.i64
ret void
}

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/sprintf-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ declare i32 @sprintf(ptr, ptr, ...)

define void @test_simplify1(ptr %dst) {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i32 13, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i64 13, i1 false)
; CHECK-NEXT: ret void
;
call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @hello_world)
Expand Down Expand Up @@ -113,7 +113,7 @@ define i32 @test_simplify7(ptr %dst, ptr %str) {
; Check sprintf(dst, "%s", str) -> llvm.memcpy(dest, str, strlen(str) + 1, 1).
define i32 @test_simplify8(ptr %dst) {
; CHECK-LABEL: @test_simplify8(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i32 13, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(13) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(13) @hello_world, i64 13, i1 false)
; CHECK-NEXT: ret i32 12
;
%r = call i32 (ptr, ptr, ...) @sprintf(ptr %dst, ptr @percent_s, ptr @hello_world)
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/stpcpy-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ define ptr @test_simplify2() {

define void @test_simplify3(ptr %dst) {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret void
;
call ptr @stpcpy(ptr dereferenceable(80) %dst, ptr @hello)
Expand Down
6 changes: 3 additions & 3 deletions llvm/test/Transforms/InstCombine/strcpy-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ declare ptr @strcpy(ptr, ptr)

define void @test_simplify1() {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret void
;

Expand All @@ -37,7 +37,7 @@ define ptr @test_simplify2() {

define void @test_simplify3(ptr %dst) {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(80) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(80) [[DST:%.*]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret void
;

Expand Down Expand Up @@ -70,7 +70,7 @@ define ptr @test_no_simplify2(ptr %dst, ptr %src) {

define void @test_no_incompatible_attr() {
; CHECK-LABEL: @test_no_incompatible_attr(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) @a, ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret void
;

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/strcpy-nonzero-as.ll
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ define void @test_strncpy_to_memcpy(ptr addrspace(200) %dst) addrspace(200) noun
; CHECK-LABEL: define {{[^@]+}}@test_strncpy_to_memcpy
; CHECK-SAME: (ptr addrspace(200) [[DST:%.*]]) addrspace(200) #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call addrspace(200) void @llvm.memcpy.p200.p200.i128(ptr addrspace(200) noundef align 1 dereferenceable(17) [[DST]], ptr addrspace(200) noundef align 1 dereferenceable(17) @str, i128 17, i1 false)
; CHECK-NEXT: call addrspace(200) void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) noundef align 1 dereferenceable(17) [[DST]], ptr addrspace(200) noundef align 1 dereferenceable(17) @str, i64 17, i1 false)
; CHECK-NEXT: ret void
;
entry:
Expand All @@ -64,7 +64,7 @@ define void @test_stpncpy_to_memcpy(ptr addrspace(200) %dst) addrspace(200) noun
; CHECK-LABEL: define {{[^@]+}}@test_stpncpy_to_memcpy
; CHECK-SAME: (ptr addrspace(200) [[DST:%.*]]) addrspace(200) #[[ATTR1]] {
; CHECK-NEXT: entry:
; CHECK-NEXT: call addrspace(200) void @llvm.memcpy.p200.p200.i128(ptr addrspace(200) noundef align 1 dereferenceable(17) [[DST]], ptr addrspace(200) noundef align 1 dereferenceable(17) @str, i128 17, i1 false)
; CHECK-NEXT: call addrspace(200) void @llvm.memcpy.p200.p200.i64(ptr addrspace(200) noundef align 1 dereferenceable(17) [[DST]], ptr addrspace(200) noundef align 1 dereferenceable(17) @str, i64 17, i1 false)
; CHECK-NEXT: ret void
;
entry:
Expand Down
8 changes: 4 additions & 4 deletions llvm/test/Transforms/InstCombine/strcpy_chk-1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f3

define ptr @test_simplify1() {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i64 12, i1 false)
; CHECK-NEXT: ret ptr @a
;

Expand All @@ -24,7 +24,7 @@ define ptr @test_simplify1() {

define ptr @test_simplify1_tail() {
; CHECK-LABEL: @test_simplify1_tail(
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false)
; CHECK-NEXT: tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i64 12, i1 false)
; CHECK-NEXT: ret ptr @a
;

Expand All @@ -34,7 +34,7 @@ define ptr @test_simplify1_tail() {

define ptr @test_simplify2() {
; CHECK-LABEL: @test_simplify2(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i64 12, i1 false)
; CHECK-NEXT: ret ptr @a
;

Expand All @@ -44,7 +44,7 @@ define ptr @test_simplify2() {

define ptr @test_simplify3() {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i32 12, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(12) @a, ptr noundef nonnull align 1 dereferenceable(12) @.str, i64 12, i1 false)
; CHECK-NEXT: ret ptr @a
;

Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/strncat-2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ define void @test_simplify1() {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) @a)
; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr @a, i32 [[STRLEN]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret void
;

Expand Down Expand Up @@ -96,7 +96,7 @@ define ptr @test5(ptr %str, i32 %n) {
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[STRLEN:%.*]] = call i32 @strlen(ptr noundef nonnull dereferenceable(1) [[STR:%.*]])
; CHECK-NEXT: [[ENDPTR:%.*]] = getelementptr inbounds i8, ptr [[STR]], i32 [[STRLEN]]
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i32 6, i1 false)
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) [[ENDPTR]], ptr noundef nonnull align 1 dereferenceable(6) @hello, i64 6, i1 false)
; CHECK-NEXT: ret ptr [[STR]]
;
%temp1 = call ptr @strncat(ptr %str, ptr @hello, i32 10)
Expand Down
Loading
Loading