Skip to content

Commit

Permalink
[MemLoc] Support memchr/memccpy in MemoryLocation::getForArgument
Browse files Browse the repository at this point in the history
Reviewed By: fhahn

Differential Revision: https://reviews.llvm.org/D89321
  • Loading branch information
davidbolvansky committed Oct 16, 2020
1 parent e034c3f commit 28691cd
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 0 deletions.
15 changes: 15 additions & 0 deletions llvm/lib/Analysis/MemoryLocation.cpp
Expand Up @@ -247,6 +247,21 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call,
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
AATags);
break;
case LibFunc_memchr:
assert((ArgIdx == 0) && "Invalid argument index for memchr");
if (const ConstantInt *LenCI =
dyn_cast<ConstantInt>(Call->getArgOperand(2)))
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
AATags);
break;
case LibFunc_memccpy:
assert((ArgIdx == 0 || ArgIdx == 1) &&
"Invalid argument index for memccpy");
if (const ConstantInt *LenCI =
dyn_cast<ConstantInt>(Call->getArgOperand(3)))
return MemoryLocation(Arg, LocationSize::precise(LenCI->getZExtValue()),
AATags);
break;
default:
break;
};
Expand Down
40 changes: 40 additions & 0 deletions llvm/test/Analysis/BasicAA/libfuncs.ll
Expand Up @@ -86,3 +86,43 @@ entry:
store i8 3, i8* %b.gep.5
ret i32 %res
}

declare i8* @memchr(i8*, i32, i64)

; CHECK-LABEL: Function: test_memchr_const_size
; CHECK: Just Ref: Ptr: i8* %res <-> %res = call i8* @memchr(i8* %a, i32 42, i64 4)
; CHECK-NEXT: Just Ref: Ptr: i8* %a.gep.1 <-> %res = call i8* @memchr(i8* %a, i32 42, i64 4)
; CHECK-NEXT: NoModRef: Ptr: i8* %a.gep.5 <-> %res = call i8* @memchr(i8* %a, i32 42, i64 4)
define i8* @test_memchr_const_size(i8* noalias %a) {
entry:
%res = call i8* @memchr(i8* %a, i32 42, i64 4)
%a.gep.1 = getelementptr i8, i8* %a, i32 1
store i8 0, i8* %a.gep.1
%a.gep.5 = getelementptr i8, i8* %a, i32 5
store i8 1, i8* %a.gep.5
ret i8* %res
}

declare i8* @memccpy(i8*, i8*, i32, i64)

; CHECK-LABEL: Function: test_memccpy_const_size
; CHECK: Both ModRef: Ptr: i8* %a <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: Just Ref: Ptr: i8* %b <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: Both ModRef: Ptr: i8* %res <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: Both ModRef: Ptr: i8* %a.gep.1 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: NoModRef: Ptr: i8* %a.gep.5 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: Just Ref: Ptr: i8* %b.gep.1 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
; CHECK-NEXT: NoModRef: Ptr: i8* %b.gep.5 <-> %res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
define i8* @test_memccpy_const_size(i8* noalias %a, i8* noalias %b) {
entry:
%res = call i8* @memccpy(i8* %a, i8* %b, i32 42, i64 4)
%a.gep.1 = getelementptr i8, i8* %a, i32 1
store i8 0, i8* %a.gep.1
%a.gep.5 = getelementptr i8, i8* %a, i32 5
store i8 1, i8* %a.gep.5
%b.gep.1 = getelementptr i8, i8* %b, i32 1
store i8 2, i8* %b.gep.1
%b.gep.5 = getelementptr i8, i8* %b, i32 5
store i8 3, i8* %b.gep.5
ret i8* %res
}
112 changes: 112 additions & 0 deletions llvm/test/Transforms/DeadStoreElimination/MSSA/libcalls.ll
Expand Up @@ -190,3 +190,115 @@ entry:
%res = icmp eq i32 %call, 0
ret i1 %res
}

declare i8* @memchr(i8*, i32, i64)

define i8* @test_memchr_const_size() {
; CHECK-LABEL: @test_memchr_const_size(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[STACK:%.*]] = alloca [10 x i8], align 1
; CHECK-NEXT: [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1
; CHECK-NEXT: [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 2)
; CHECK-NEXT: ret i8* [[CALL]]
;
entry:
%stack = alloca [10 x i8]
%stack.ptr = bitcast [10 x i8]* %stack to i8*
store i8 49, i8* %stack.ptr, align 1
%gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
store i8 50, i8* %gep.1, align 1
%gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
store i8 51, i8* %gep.2, align 1
%gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
store i8 52, i8* %gep.3, align 1
%call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 2)
ret i8* %call
}

define i8* @test_memchr_variable_size(i64 %n) {
; CHECK-LABEL: @test_memchr_variable_size(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[STACK:%.*]] = alloca [10 x i8], align 1
; CHECK-NEXT: [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 4
; CHECK-NEXT: store i8 52, i8* [[GEP]], align 1
; CHECK-NEXT: [[CALL:%.*]] = call i8* @memchr(i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[CALL]]
;
entry:
%stack = alloca [10 x i8]
%stack.ptr = bitcast [10 x i8]* %stack to i8*
store i8 49, i8* %stack.ptr, align 1
%gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
store i8 50, i8* %gep.1, align 1
%gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
store i8 51, i8* %gep.2, align 1
%gep = getelementptr i8, i8* %stack.ptr, i64 4
store i8 52, i8* %gep, align 1
%call = call i8* @memchr(i8* %stack.ptr, i32 42, i64 %n)
ret i8* %call
}

declare i8* @memccpy(i8*, i8*, i32, i64)

define i8* @test_memccpy_const_size(i8* %foo) {
; CHECK-LABEL: @test_memccpy_const_size(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[STACK:%.*]] = alloca [10 x i8], align 1
; CHECK-NEXT: [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1
; CHECK-NEXT: [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 2)
; CHECK-NEXT: ret i8* [[RES]]
;
entry:
%stack = alloca [10 x i8]
%stack.ptr = bitcast [10 x i8]* %stack to i8*
store i8 49, i8* %stack.ptr, align 1
%gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
store i8 50, i8* %gep.1, align 1
%gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
store i8 51, i8* %gep.2, align 1
%gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
store i8 52, i8* %gep.3, align 1
%res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 2)
ret i8* %res
}

define i8* @test_memccpy_variable_size(i8* %foo, i64 %n) {
; CHECK-LABEL: @test_memccpy_variable_size(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[STACK:%.*]] = alloca [10 x i8], align 1
; CHECK-NEXT: [[STACK_PTR:%.*]] = bitcast [10 x i8]* [[STACK]] to i8*
; CHECK-NEXT: store i8 49, i8* [[STACK_PTR]], align 1
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 1
; CHECK-NEXT: store i8 50, i8* [[GEP_1]], align 1
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 2
; CHECK-NEXT: store i8 51, i8* [[GEP_2]], align 1
; CHECK-NEXT: [[GEP_3:%.*]] = getelementptr i8, i8* [[STACK_PTR]], i64 3
; CHECK-NEXT: store i8 52, i8* [[GEP_3]], align 1
; CHECK-NEXT: [[RES:%.*]] = call i8* @memccpy(i8* [[FOO:%.*]], i8* [[STACK_PTR]], i32 42, i64 [[N:%.*]])
; CHECK-NEXT: ret i8* [[RES]]
;
entry:
%stack = alloca [10 x i8]
%stack.ptr = bitcast [10 x i8]* %stack to i8*
store i8 49, i8* %stack.ptr, align 1
%gep.1 = getelementptr i8, i8* %stack.ptr, i64 1
store i8 50, i8* %gep.1, align 1
%gep.2 = getelementptr i8, i8* %stack.ptr, i64 2
store i8 51, i8* %gep.2, align 1
%gep.3 = getelementptr i8, i8* %stack.ptr, i64 3
store i8 52, i8* %gep.3, align 1
%res = call i8* @memccpy(i8* %foo, i8* %stack.ptr, i32 42, i64 %n)
ret i8* %res
}

0 comments on commit 28691cd

Please sign in to comment.