[PATCH] D99737: Infer dereferenceability from malloc and friends

Philip Reames via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 1 08:55:33 PDT 2021


reames created this revision.
reames added reviewers: nikic, jdoerfert.
Herald added subscribers: dantrushin, asbirlea, hiraditya, mcrosier.
Herald added a reviewer: bollu.
reames requested review of this revision.
Herald added a project: LLVM.

Hookup TLI when inferring object size from allocation calls.  This allows the analysis to prove dereferenceability for known allocation functions (such as malloc/new/etc) in addition to those marked explicitly with the allocsize attribute.

This is a follow up to 0129cd5 <https://reviews.llvm.org/rG0129cd503575076556935a16f458b0a3c2e30646> now that the bug fixed by e2c6621e6 <https://reviews.llvm.org/rGe2c6621e638e4dc30963293bff052784d3a3305a> is resolved.

As noted in the test, this relies on being able to prove that there is no free between allocation and context (e.g. hoist location).  At the moment, this is handled conservatively.  I'm working strengthening out ability to reason about no-free regions separately.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D99737

Files:
  llvm/lib/Analysis/Loads.cpp
  llvm/test/Transforms/LICM/hoist-alloc.ll


Index: llvm/test/Transforms/LICM/hoist-alloc.ll
===================================================================
--- llvm/test/Transforms/LICM/hoist-alloc.ll
+++ llvm/test/Transforms/LICM/hoist-alloc.ll
@@ -130,7 +130,8 @@
   ret i8 %res
 }
 
-; TODO: We can hoist the load in this case.
+; TODO: We can hoist the load in this case, but only once we have
+; some form of context sensitive free analysis.
 define i8 @test_hoist_malloc() {
 ; CHECK-LABEL: @test_hoist_malloc(
 ; CHECK-NEXT:  entry:
@@ -171,18 +172,17 @@
   ret i8 %res
 }
 
-; TODO: We can hoist the load in this case.
-define i8 @test_hoist_malloc_leak() {
+define i8 @test_hoist_malloc_leak() nofree nosync {
 ; CHECK-LABEL: @test_hoist_malloc_leak(
 ; CHECK-NEXT:  entry:
 ; CHECK-NEXT:    [[A_RAW:%.*]] = call nonnull i8* @malloc(i64 32)
 ; CHECK-NEXT:    call void @init(i8* [[A_RAW]])
 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr i8, i8* [[A_RAW]], i32 31
+; CHECK-NEXT:    [[RES:%.*]] = load i8, i8* [[ADDR]], align 1
 ; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
 ; CHECK:       for.body:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[FOR_BODY]] ], [ 0, [[ENTRY:%.*]] ]
 ; CHECK-NEXT:    call void @unknown()
-; CHECK-NEXT:    [[RES:%.*]] = load i8, i8* [[ADDR]], align 1
 ; CHECK-NEXT:    call void @use(i8 [[RES]])
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i64 [[IV_NEXT]], 200
Index: llvm/lib/Analysis/Loads.cpp
===================================================================
--- llvm/lib/Analysis/Loads.cpp
+++ llvm/lib/Analysis/Loads.cpp
@@ -162,8 +162,7 @@
     Opts.RoundToAlign = false;
     Opts.NullIsUnknownSize = true;
     uint64_t ObjSize;
-    // TODO: Plumb through TLI so that malloc routines and such work.
-    if (getObjectSize(V, ObjSize, DL, nullptr, Opts)) {
+    if (getObjectSize(V, ObjSize, DL, TLI, Opts)) {
       APInt KnownDerefBytes(Size.getBitWidth(), ObjSize);
       if (KnownDerefBytes.getBoolValue() && KnownDerefBytes.uge(Size) &&
           isKnownNonZero(V, DL, 0, nullptr, CtxI, DT) && !V->canBeFreed()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D99737.334717.patch
Type: text/x-patch
Size: 2101 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210401/2d9ef1df/attachment.bin>


More information about the llvm-commits mailing list