From 217067d5179882de9deb60d2e866befea4c126e7 Mon Sep 17 00:00:00 2001 From: Bjorn Steinbrink Date: Sun, 17 Dec 2017 01:54:25 +0000 Subject: [PATCH] Properly handle multi-element and dynamically sized allocas in getPointerDereferenceableBytes() Reviewers: hfinkel, rnk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D41288 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320938 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Value.h | 2 +- lib/IR/Value.cpp | 10 ++++++---- test/Analysis/ValueTracking/memory-dereferenceable.ll | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index f3bcba0a03f..d848fe92186 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -570,7 +570,7 @@ public: /// /// If CanBeNull is set by this function the pointer can either be null or be /// dereferenceable up to the returned number of bytes. - unsigned getPointerDereferenceableBytes(const DataLayout &DL, + uint64_t getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull) const; /// \brief Returns an alignment of the pointer value. diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 19b2535fbd6..6f67be78f8a 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -619,11 +619,11 @@ const Value *Value::stripInBoundsOffsets() const { return stripPointerCastsAndOffsets(this); } -unsigned Value::getPointerDereferenceableBytes(const DataLayout &DL, +uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL, bool &CanBeNull) const { assert(getType()->isPointerTy() && "must be pointer"); - unsigned DerefBytes = 0; + uint64_t DerefBytes = 0; CanBeNull = false; if (const Argument *A = dyn_cast(this)) { DerefBytes = A->getDereferenceableBytes(); @@ -655,8 +655,10 @@ unsigned Value::getPointerDereferenceableBytes(const DataLayout &DL, CanBeNull = true; } } else if (auto *AI = dyn_cast(this)) { - if (AI->getAllocatedType()->isSized()) { - DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()); + const ConstantInt *ArraySize = dyn_cast(AI->getArraySize()); + if (ArraySize && AI->getAllocatedType()->isSized()) { + DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()) * + ArraySize->getZExtValue(); CanBeNull = false; } } else if (auto *GV = dyn_cast(this)) { diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll index 29c31b95b18..315a0114a16 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -34,6 +34,23 @@ entry: %alloca = alloca i1 %load2 = load i1, i1* %alloca + ; Load from empty array alloca +; CHECK-NOT: %empty_alloca + %empty_alloca = alloca i8, i64 0 + %empty_load = load i8, i8* %empty_alloca + + ; Load from too small array alloca +; CHECK-NOT: %small_array_alloca + %small_array_alloca = alloca i8, i64 2 + %saa_cast = bitcast i8* %small_array_alloca to i32* + %saa_load = load i32, i32* %saa_cast + + ; Load from array alloca +; CHECK: %big_array_alloca{{.*}}(unaligned) + %big_array_alloca = alloca i8, i64 4 + %baa_cast = bitcast i8* %big_array_alloca to i32* + %baa_load = load i32, i32* %baa_cast + ; CHECK: %dparam{{.*}}(aligned) %load3 = load i32, i32 addrspace(1)* %dparam -- 2.11.0