Index: llvm/trunk/include/llvm/IR/Value.h =================================================================== --- llvm/trunk/include/llvm/IR/Value.h +++ llvm/trunk/include/llvm/IR/Value.h @@ -570,7 +570,7 @@ /// /// 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. Index: llvm/trunk/lib/IR/Value.cpp =================================================================== --- llvm/trunk/lib/IR/Value.cpp +++ llvm/trunk/lib/IR/Value.cpp @@ -619,11 +619,11 @@ 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 @@ 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)) { Index: llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll =================================================================== --- llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ llvm/trunk/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -34,6 +34,23 @@ %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