[llvm] 8c74169 - [SimplifyLibCalls] Don't mark memchr() memory as fully dereferenceable

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 13 07:46:26 PDT 2022


Author: Nikita Popov
Date: 2022-04-13T16:46:18+02:00
New Revision: 8c74169990c0b179fa9a0c82f8d6ca35889b9ec4

URL: https://github.com/llvm/llvm-project/commit/8c74169990c0b179fa9a0c82f8d6ca35889b9ec4
DIFF: https://github.com/llvm/llvm-project/commit/8c74169990c0b179fa9a0c82f8d6ca35889b9ec4.diff

LOG: [SimplifyLibCalls] Don't mark memchr() memory as fully dereferenceable

C11 specifies memchr() as follows:

> The memchr function locates the first occurrence of c (converted
> to an unsigned char) in the initial n characters (each interpreted
> as unsigned char) of the object pointed to by s. The implementation
> shall behave as if it reads the characters sequentially and stops
> as soon as a matching character is found.

In particular, it is well-defined to specify a memchr size larger
than the underlying object, as long as the character is found before
the end of the object.

Differential Revision: https://reviews.llvm.org/D123665

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/test/Transforms/InstCombine/mem-deref-bytes.ll
    llvm/test/Transforms/InstCombine/memchr.ll
    llvm/test/Transforms/InstCombine/strchr-1.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 2da6355d9eaae..537e90a8bc7df 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -876,7 +876,9 @@ Value *LibCallSimplifier::optimizeMemRChr(CallInst *CI, IRBuilderBase &B) {
 Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilderBase &B) {
   Value *SrcStr = CI->getArgOperand(0);
   Value *Size = CI->getArgOperand(2);
-  annotateNonNullAndDereferenceable(CI, 0, Size, DL);
+  if (isKnownNonZero(Size, DL))
+    annotateNonNullNoUndefBasedOnAccess(CI, 0);
+
   Value *CharVal = CI->getArgOperand(1);
   ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
   ConstantInt *LenC = dyn_cast<ConstantInt>(Size);

diff  --git a/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll b/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll
index 22797c20a5a4f..680ff2dd9a76d 100644
--- a/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll
+++ b/llvm/test/Transforms/InstCombine/mem-deref-bytes.ll
@@ -102,7 +102,7 @@ define i32 @memcmp_nonconst_size(i8* nocapture readonly %d, i8* nocapture readon
 
 define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) {
 ; CHECK-LABEL: @memcpy_const_size_set_deref(
-; CHECK-NEXT:    call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[D:%.*]], i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
+; CHECK-NEXT:    tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[D:%.*]], i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
 ; CHECK-NEXT:    ret i8* [[D]]
 ;
   %call = tail call i8* @memcpy(i8* %d, i8* %s, i64 64)
@@ -111,7 +111,7 @@ define i8* @memcpy_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture
 
 define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocapture readonly %s) {
 ; CHECK-LABEL: @memmove_const_size_set_deref(
-; CHECK-NEXT:    call void @llvm.memmove.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[D:%.*]], i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
+; CHECK-NEXT:    tail call void @llvm.memmove.p0i8.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[D:%.*]], i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i64 64, i1 false)
 ; CHECK-NEXT:    ret i8* [[D]]
 ;
   %call = tail call i8* @memmove(i8* %d, i8* %s, i64 64)
@@ -120,7 +120,7 @@ define i8* @memmove_const_size_set_deref(i8* nocapture readonly %d, i8* nocaptur
 
 define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) {
 ; CHECK-LABEL: @memset_const_size_set_deref(
-; CHECK-NEXT:    call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false)
+; CHECK-NEXT:    tail call void @llvm.memset.p0i8.i64(i8* noundef nonnull align 1 dereferenceable(64) [[S:%.*]], i8 [[C:%.*]], i64 64, i1 false)
 ; CHECK-NEXT:    ret i8* [[S]]
 ;
   %call = tail call i8* @memset(i8* %s, i8 %c, i64 64)
@@ -129,7 +129,7 @@ define i8* @memset_const_size_set_deref(i8* nocapture readonly %s, i8 %c) {
 
 define i8* @memchr_const_size_set_deref(i8* nocapture readonly %s, i32 %c) {
 ; CHECK-LABEL: @memchr_const_size_set_deref(
-; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @memchr(i8* noundef nonnull dereferenceable(64) [[S:%.*]], i32 [[C:%.*]], i64 64)
+; CHECK-NEXT:    [[CALL:%.*]] = tail call i8* @memchr(i8* noundef nonnull dereferenceable(1) [[S:%.*]], i32 [[C:%.*]], i64 64)
 ; CHECK-NEXT:    ret i8* [[CALL]]
 ;
   %call = tail call i8* @memchr(i8* %s, i32 %c, i64 64)

diff  --git a/llvm/test/Transforms/InstCombine/memchr.ll b/llvm/test/Transforms/InstCombine/memchr.ll
index dcf175139c560..c702964b3f180 100644
--- a/llvm/test/Transforms/InstCombine/memchr.ll
+++ b/llvm/test/Transforms/InstCombine/memchr.ll
@@ -50,7 +50,7 @@ define void @test3() {
 
 define void @test4(i32 %chr) {
 ; CHECK-LABEL: @test4(
-; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14)
+; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14)
 ; CHECK-NEXT:    store i8* [[DST]], i8** @chp, align 4
 ; CHECK-NEXT:    ret void
 ;
@@ -148,7 +148,7 @@ define i1 @test11(i32 %C) {
 ; No 64 bits here
 define i1 @test12(i32 %C) {
 ; CHECK-LABEL: @test12(
-; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(3) getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3)
+; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([4 x i8], [4 x i8]* @spaces, i32 0, i32 0), i32 [[C:%.*]], i32 3)
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8* [[DST]], null
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
@@ -185,7 +185,7 @@ define i1 @test14(i32 %C) {
 
 define i1 @test15(i32 %C) {
 ; CHECK-LABEL: @test15(
-; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(3) getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3)
+; CHECK-NEXT:    [[DST:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([3 x i8], [3 x i8]* @negative, i32 0, i32 0), i32 [[C:%.*]], i32 3)
 ; CHECK-NEXT:    [[CMP:%.*]] = icmp ne i8* [[DST]], null
 ; CHECK-NEXT:    ret i1 [[CMP]]
 ;
@@ -225,7 +225,7 @@ define i8* @test17(i8* %str, i32 %c, i32 %n) {
 
 define i8* @test18(i8* %str, i32 %c) {
 ; CHECK-LABEL: @test18(
-; CHECK-NEXT:    [[RET:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(5) [[STR:%.*]], i32 [[C:%.*]], i32 5)
+; CHECK-NEXT:    [[RET:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) [[STR:%.*]], i32 [[C:%.*]], i32 5)
 ; CHECK-NEXT:    ret i8* [[RET]]
 ;
 
@@ -235,7 +235,7 @@ define i8* @test18(i8* %str, i32 %c) {
 
 define i8* @test19(i8* %str, i32 %c) null_pointer_is_valid {
 ; CHECK-LABEL: @test19(
-; CHECK-NEXT:    [[RET:%.*]] = call i8* @memchr(i8* noundef dereferenceable(5) [[STR:%.*]], i32 [[C:%.*]], i32 5)
+; CHECK-NEXT:    [[RET:%.*]] = call i8* @memchr(i8* noundef [[STR:%.*]], i32 [[C:%.*]], i32 5)
 ; CHECK-NEXT:    ret i8* [[RET]]
 ;
 

diff  --git a/llvm/test/Transforms/InstCombine/strchr-1.ll b/llvm/test/Transforms/InstCombine/strchr-1.ll
index 86ac9dafc91fe..cb6b3ad204ffb 100644
--- a/llvm/test/Transforms/InstCombine/strchr-1.ll
+++ b/llvm/test/Transforms/InstCombine/strchr-1.ll
@@ -49,7 +49,7 @@ define void @test_simplify3() {
 
 define void @test_simplify4(i32 %chr) {
 ; CHECK-LABEL: @test_simplify4(
-; CHECK-NEXT:    [[MEMCHR:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(14) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14)
+; CHECK-NEXT:    [[MEMCHR:%.*]] = call i8* @memchr(i8* noundef nonnull dereferenceable(1) getelementptr inbounds ([14 x i8], [14 x i8]* @hello, i32 0, i32 0), i32 [[CHR:%.*]], i32 14)
 ; CHECK-NEXT:    store i8* [[MEMCHR]], i8** @chp, align 4
 ; CHECK-NEXT:    ret void
 ;


        


More information about the llvm-commits mailing list