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 @@ -23,7 +23,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" @@ -299,6 +299,12 @@ ArrayRef Operands, Type *AccessType = nullptr, TargetCostKind CostKind = TCK_SizeAndLatency) const; + // Helper function for using getGEPCost on an already materialized GEP + // instruction. Uses the first user as an approximation for AccessType. + InstructionCost + getGEPCost(const GetElementPtrInst *GEP, + TargetCostKind CostKind = TCK_SizeAndLatency) const; + /// Describe known properties for a set of pointers. struct PointersChainInfo { /// All the GEPs in a set have same base address. diff --git a/llvm/lib/Analysis/TargetTransformInfo.cpp b/llvm/lib/Analysis/TargetTransformInfo.cpp --- a/llvm/lib/Analysis/TargetTransformInfo.cpp +++ b/llvm/lib/Analysis/TargetTransformInfo.cpp @@ -232,6 +232,20 @@ return TTIImpl->getGEPCost(PointeeType, Ptr, Operands, AccessType, CostKind); } +InstructionCost +TargetTransformInfo::getGEPCost(const GetElementPtrInst *GEP, + TTI::TargetCostKind CostKind) const { + Type *AccessType = nullptr; + if (!GEP->user_empty()) { + // Only take into account the first user as a rough approximation to avoid + // O(N) complexity. + AccessType = GEP->user_back()->getAccessType(); + } + SmallVector Ops(GEP->indices()); + return getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), Ops, + AccessType, CostKind); +} + InstructionCost TargetTransformInfo::getPointersChainCost( ArrayRef Ptrs, const Value *Base, const TTI::PointersChainInfo &Info, Type *AccessTy, 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 @@ -325,16 +325,9 @@ return nullptr; } -static bool isGEPFoldable(GetElementPtrInst *GEP, - const TargetTransformInfo *TTI) { - SmallVector Indices(GEP->indices()); - return TTI->getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), - Indices) == TargetTransformInfo::TCC_Free; -} - Instruction *NaryReassociatePass::tryReassociateGEP(GetElementPtrInst *GEP) { // Not worth reassociating GEP if it is foldable. - if (isGEPFoldable(GEP, TTI)) + if (TTI->getGEPCost(GEP) == TTI::TCC_Free) return nullptr; gep_type_iterator GTI = gep_type_begin(*GEP);