diff --git a/llvm/include/llvm/Analysis/TargetTransformInfo.h b/llvm/include/llvm/Analysis/TargetTransformInfo.h --- a/llvm/include/llvm/Analysis/TargetTransformInfo.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfo.h @@ -24,6 +24,7 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/IR/FMF.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/PassManager.h" #include "llvm/Pass.h" #include "llvm/Support/AtomicOrdering.h" @@ -298,6 +299,21 @@ ArrayRef Operands, Type *AccessType = nullptr, TargetCostKind CostKind = TCK_SizeAndLatency) const; + // Helper function for using getGEPCost on an already materialized GEP + // instruction. + InstructionCost + getGEPCost(const GetElementPtrInst *GEP, + TargetCostKind CostKind = TCK_SizeAndLatency) const { + Type *AccessType = nullptr; + // For now, only provide the AccessType in the simple case where the GEP + // only has one user. + if (GEP->hasOneUser()) + AccessType = GEP->user_back()->getAccessType(); + return getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), + SmallVector(GEP->indices()), AccessType, + CostKind); + } + /// Describe known properties for a set of pointers. struct PointersChainInfo { /// All the GEPs in a set have same base address. diff --git a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h --- a/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/llvm/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -1095,7 +1095,7 @@ SmallVector Indices(GEP->indices()); Cost += static_cast(this)->getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), - Indices, nullptr, CostKind); + Indices, AccessTy, CostKind); } } return Cost; diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -1641,7 +1641,7 @@ } else { SmallVector Indices(GEP->indices()); Cost += getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), - Indices, nullptr, CostKind); + Indices, AccessTy, CostKind); } } return Cost; diff --git a/llvm/lib/Transforms/Scalar/NaryReassociate.cpp b/llvm/lib/Transforms/Scalar/NaryReassociate.cpp --- a/llvm/lib/Transforms/Scalar/NaryReassociate.cpp +++ b/llvm/lib/Transforms/Scalar/NaryReassociate.cpp @@ -327,9 +327,7 @@ static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI) { - SmallVector Indices(GEP->indices()); - return TTI->getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), - Indices) == TargetTransformInfo::TCC_Free; + return TTI->getGEPCost(GEP) == TargetTransformInfo::TCC_Free; } Instruction *NaryReassociatePass::tryReassociateGEP(GetElementPtrInst *GEP) { diff --git a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp --- a/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp @@ -284,9 +284,7 @@ static bool isGEPFoldable(GetElementPtrInst *GEP, const TargetTransformInfo *TTI) { - SmallVector Indices(GEP->indices()); - return TTI->getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), - Indices) == TargetTransformInfo::TCC_Free; + return TTI->getGEPCost(GEP) == TargetTransformInfo::TCC_Free; } // Returns whether (Base + Index * Stride) can be folded to an addressing mode. diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp --- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp +++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp @@ -7438,15 +7438,10 @@ ScalarCost = TTI->getPointersChainCost(Ptrs, BasePtr, PtrsInfo, ScalarTy, CostKind); - - // Remark: it not quite correct to use scalar GEP cost for a vector GEP, - // but it's not clear how to do that without having vector GEP arguments - // ready. - // Perhaps using just TTI::TCC_Free/TTI::TCC_Basic would be better option. - if (const auto *Base = dyn_cast(BasePtr)) { - SmallVector Indices(Base->indices()); - VecCost = TTI->getGEPCost(Base->getSourceElementType(), - Base->getPointerOperand(), Indices, nullptr, + if (auto *BaseGEP = dyn_cast(BasePtr)) { + SmallVector Indices(BaseGEP->indices()); + VecCost = TTI->getGEPCost(BaseGEP->getSourceElementType(), + BaseGEP->getPointerOperand(), Indices, VecTy, CostKind); } } diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll --- a/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll +++ b/llvm/test/Transforms/SLPVectorizer/RISCV/gep.ll @@ -2,8 +2,8 @@ ; RUN: opt < %s -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v \ ; RUN: -riscv-v-slp-max-vf=0 -S | FileCheck %s -; FIXME: This should not be vectorized, as the cost of computing the -; offsets nullifies the benefits of vectorizing: +; This should not be vectorized, as the cost of computing the offsets nullifies +; the benefits of vectorizing: ; ; copy_with_offset_v2i8: ; addi a0, a0, 8 @@ -27,9 +27,13 @@ ; CHECK-LABEL: @copy_with_offset_v2i8( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[P1:%.*]] = getelementptr i8, ptr [[P:%.*]], i32 8 +; CHECK-NEXT: [[X1:%.*]] = load i8, ptr [[P1]], align 1 ; CHECK-NEXT: [[Q1:%.*]] = getelementptr i8, ptr [[Q:%.*]], i32 16 -; CHECK-NEXT: [[TMP0:%.*]] = load <2 x i8>, ptr [[P1]], align 1 -; CHECK-NEXT: store <2 x i8> [[TMP0]], ptr [[Q1]], align 1 +; CHECK-NEXT: store i8 [[X1]], ptr [[Q1]], align 1 +; CHECK-NEXT: [[P2:%.*]] = getelementptr i8, ptr [[P]], i32 9 +; CHECK-NEXT: [[X2:%.*]] = load i8, ptr [[P2]], align 1 +; CHECK-NEXT: [[Q2:%.*]] = getelementptr i8, ptr [[Q]], i32 17 +; CHECK-NEXT: store i8 [[X2]], ptr [[Q2]], align 1 ; CHECK-NEXT: ret void ; entry: