diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h --- a/llvm/include/llvm/Analysis/ScalarEvolution.h +++ b/llvm/include/llvm/Analysis/ScalarEvolution.h @@ -599,9 +599,17 @@ return getConstant(Ty, -1, /*isSigned=*/true); } - /// Return an expression for sizeof AllocTy that is type IntTy + /// Return an expression for sizeof ScalableTy that is type IntTy, where + /// ScalableTy is a scalable vector type. + const SCEV *getSizeOfScalableVectorExpr(Type *IntTy, + ScalableVectorType *ScalableTy); + + /// Return an expression for the alloc size of AllocTy that is type IntTy const SCEV *getSizeOfExpr(Type *IntTy, Type *AllocTy); + /// Return an expression for the store size of StoreTy that is type IntTy + const SCEV *getStoreSizeOfExpr(Type *IntTy, Type *StoreTy); + /// Return an expression for offsetof on the given field with type IntTy const SCEV *getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo); diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -228,9 +228,9 @@ } // Add the size of the pointed element to ScEnd. auto &DL = Lp->getHeader()->getModule()->getDataLayout(); - unsigned EltSize = - DL.getTypeStoreSizeInBits(Ptr->getType()->getPointerElementType()) / 8; - const SCEV *EltSizeSCEV = SE->getConstant(ScEnd->getType(), EltSize); + Type *IdxTy = DL.getIndexType(Ptr->getType()); + const SCEV *EltSizeSCEV = + SE->getStoreSizeOfExpr(IdxTy, Ptr->getType()->getPointerElementType()); ScEnd = SE->getAddExpr(ScEnd, EltSizeSCEV); } diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -3522,19 +3522,33 @@ return getMinMaxExpr(scUMinExpr, Ops); } +const SCEV * +ScalarEvolution::getSizeOfScalableVectorExpr(Type *IntTy, + ScalableVectorType *ScalableTy) { + Constant *NullPtr = Constant::getNullValue(ScalableTy->getPointerTo()); + Constant *One = ConstantInt::get(IntTy, 1); + Constant *GEP = ConstantExpr::getGetElementPtr(ScalableTy, NullPtr, One); + return getSCEV(ConstantExpr::getPtrToInt(GEP, IntTy)); +} + const SCEV *ScalarEvolution::getSizeOfExpr(Type *IntTy, Type *AllocTy) { // We can bypass creating a target-independent // constant expression and then folding it back into a ConstantInt. // This is just a compile-time optimization. - if (isa(AllocTy)) { - Constant *NullPtr = Constant::getNullValue(AllocTy->getPointerTo()); - Constant *One = ConstantInt::get(IntTy, 1); - Constant *GEP = ConstantExpr::getGetElementPtr(AllocTy, NullPtr, One); - return getSCEV(ConstantExpr::getPtrToInt(GEP, IntTy)); - } + if (auto *ScalableAllocTy = dyn_cast(AllocTy)) + return getSizeOfScalableVectorExpr(IntTy, ScalableAllocTy); return getConstant(IntTy, getDataLayout().getTypeAllocSize(AllocTy)); } +const SCEV *ScalarEvolution::getStoreSizeOfExpr(Type *IntTy, Type *StoreTy) { + // We can bypass creating a target-independent + // constant expression and then folding it back into a ConstantInt. + // This is just a compile-time optimization. + if (auto *ScalableStoreTy = dyn_cast(StoreTy)) + return getSizeOfScalableVectorExpr(IntTy, ScalableStoreTy); + return getConstant(IntTy, getDataLayout().getTypeStoreSize(StoreTy)); +} + const SCEV *ScalarEvolution::getOffsetOfExpr(Type *IntTy, StructType *STy, unsigned FieldNo) { diff --git a/llvm/test/Analysis/LoopAccessAnalysis/runtime-pointer-checking-insert-typesize.ll b/llvm/test/Analysis/LoopAccessAnalysis/runtime-pointer-checking-insert-typesize.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/LoopAccessAnalysis/runtime-pointer-checking-insert-typesize.ll @@ -0,0 +1,27 @@ +; RUN: opt -loop-accesses -analyze < %s >/dev/null 2>%t +; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t + +; This regression test is defending against a TypeSize warning 'assumption that +; TypeSize is not scalable'. This warning cropped up in +; RuntimePointerChecking::insert when performing loop load elimination because +; this function was previously unaware of scalable types. + +; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it. +; WARN-NOT: warning: {{.*}}TypeSize is not scalable + +define void @runtime_pointer_checking_insert_typesize(* %a, + * %b) { +entry: + br label %loop.body +loop.body: + %0 = phi i64 [ 0, %entry ], [%1, %loop.body] + %idx_a = getelementptr , * %a, i64 %0 + %idx_b = getelementptr , * %b, i64 %0 + %tmp = load , * %idx_a + store %tmp, * %idx_b + %1 = add i64 %0, 2 + %2 = icmp eq i64 %1, 1024 + br i1 %2, label %loop.end, label %loop.body +loop.end: + ret void +}