From 53f8289df4894f4c5e9775f165b85faab8014afd Mon Sep 17 00:00:00 2001 From: Bjorn Steinbrink Date: Sun, 17 Dec 2017 21:20:16 +0000 Subject: [PATCH] Re-commit "Properly handle multi-element and dynamically sized allocas in getPointerDereferenceableBytes()"" llvm-clang-x86_64-expensive-checks-win is still broken, so the failure seems unrelated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320953 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Value.h | 2 +- lib/IR/Value.cpp | 10 ++++++---- .../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 773ed89db04..eae697b2e4b 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 999486d34c2..ca16a266123 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -36,6 +36,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