diff options
Diffstat (limited to 'include/llvm/Analysis/TargetTransformInfoImpl.h')
-rw-r--r-- | include/llvm/Analysis/TargetTransformInfoImpl.h | 104 |
1 files changed, 91 insertions, 13 deletions
diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 9bbda718acab4..4c37402278efe 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -152,6 +152,7 @@ public: case Intrinsic::annotation: case Intrinsic::assume: + case Intrinsic::sideeffect: case Intrinsic::dbg_declare: case Intrinsic::dbg_value: case Intrinsic::invariant_start: @@ -188,6 +189,8 @@ public: } bool isLoweredToCall(const Function *F) { + assert(F && "A concrete function must be provided to this routine."); + // FIXME: These should almost certainly not be handled here, and instead // handled with the help of TLI or the target itself. This was largely // ported from existing analysis heuristics here so that such refactorings @@ -230,7 +233,7 @@ public: bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale, - unsigned AddrSpace) { + unsigned AddrSpace, Instruction *I = nullptr) { // Guess that only reg and reg+reg addressing is allowed. This heuristic is // taken from the implementation of LSR. return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); @@ -251,6 +254,10 @@ public: bool isLegalMaskedGather(Type *DataType) { return false; } + bool hasDivRemOp(Type *DataType, bool IsSigned) { return false; } + + bool hasVolatileVariant(Instruction *I, unsigned AddrSpace) { return false; } + bool prefersVectorizedAddressing() { return true; } int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, @@ -262,7 +269,7 @@ public: return -1; } - bool isFoldableMemAccessOffset(Instruction *I, int64_t Offset) { return true; } + bool LSRWithInstrQueries() { return false; } bool isTruncateFree(Type *Ty1, Type *Ty2) { return false; } @@ -288,7 +295,10 @@ public: bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; } - bool expandMemCmp(Instruction *I, unsigned &MaxLoadSize) { return false; } + const TTI::MemCmpExpansionOptions *enableMemCmpExpansion( + bool IsZeroCmp) const { + return nullptr; + } bool enableInterleavedAccessVectorization() { return false; } @@ -306,6 +316,8 @@ public: bool haveFastSqrt(Type *Ty) { return false; } + bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) { return true; } + unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } int getIntImmCodeSizeCost(unsigned Opcode, unsigned Idx, const APInt &Imm, @@ -340,6 +352,29 @@ public: unsigned getCacheLineSize() { return 0; } + llvm::Optional<unsigned> getCacheSize(TargetTransformInfo::CacheLevel Level) { + switch (Level) { + case TargetTransformInfo::CacheLevel::L1D: + LLVM_FALLTHROUGH; + case TargetTransformInfo::CacheLevel::L2D: + return llvm::Optional<unsigned>(); + } + + llvm_unreachable("Unknown TargetTransformInfo::CacheLevel"); + } + + llvm::Optional<unsigned> getCacheAssociativity( + TargetTransformInfo::CacheLevel Level) { + switch (Level) { + case TargetTransformInfo::CacheLevel::L1D: + LLVM_FALLTHROUGH; + case TargetTransformInfo::CacheLevel::L2D: + return llvm::Optional<unsigned>(); + } + + llvm_unreachable("Unknown TargetTransformInfo::CacheLevel"); + } + unsigned getPrefetchDistance() { return 0; } unsigned getMinPrefetchStride() { return 1; } @@ -423,10 +458,12 @@ public: unsigned getAddressComputationCost(Type *Tp, ScalarEvolution *, const SCEV *) { - return 0; + return 0; } - unsigned getReductionCost(unsigned, Type *, bool) { return 1; } + unsigned getArithmeticReductionCost(unsigned, Type *, bool) { return 1; } + + unsigned getMinMaxReductionCost(Type *, Type *, bool, bool) { return 1; } unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { return 0; } @@ -587,7 +624,7 @@ protected: APInt StrideVal = Step->getAPInt(); if (StrideVal.getBitWidth() > 64) return false; - // FIXME: need to take absolute value for negtive stride case + // FIXME: Need to take absolute value for negative stride case. return StrideVal.getSExtValue() < MergeDistance; } }; @@ -647,11 +684,13 @@ public: BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts()); } bool HasBaseReg = (BaseGV == nullptr); - int64_t BaseOffset = 0; + + auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType()); + APInt BaseOffset(PtrSizeBits, 0); int64_t Scale = 0; auto GTI = gep_type_begin(PointeeType, Operands); - Type *TargetType; + Type *TargetType = nullptr; // Handle the case where the GEP instruction has a single operand, // the basis, therefore TargetType is a nullptr. @@ -673,9 +712,10 @@ public: BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field); } else { int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType()); - if (ConstIdx) - BaseOffset += ConstIdx->getSExtValue() * ElementSize; - else { + if (ConstIdx) { + BaseOffset += + ConstIdx->getValue().sextOrTrunc(PtrSizeBits) * ElementSize; + } else { // Needs scale register. if (Scale != 0) // No addressing mode takes two scale registers. @@ -688,9 +728,10 @@ public: // Assumes the address space is 0 when Ptr is nullptr. unsigned AS = (Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace()); + if (static_cast<T *>(this)->isLegalAddressingMode( - TargetType, const_cast<GlobalValue *>(BaseGV), BaseOffset, - HasBaseReg, Scale, AS)) + TargetType, const_cast<GlobalValue *>(BaseGV), + BaseOffset.sextOrTrunc(64).getSExtValue(), HasBaseReg, Scale, AS)) return TTI::TCC_Free; return TTI::TCC_Basic; } @@ -713,6 +754,11 @@ public: if (isa<PHINode>(U)) return TTI::TCC_Free; // Model all PHI nodes as free. + // Static alloca doesn't generate target instructions. + if (auto *A = dyn_cast<AllocaInst>(U)) + if (A->isStaticAlloca()) + return TTI::TCC_Free; + if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) { return static_cast<T *>(this)->getGEPCost(GEP->getSourceElementType(), GEP->getPointerOperand(), @@ -746,6 +792,38 @@ public: Operator::getOpcode(U), U->getType(), U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); } + + int getInstructionLatency(const Instruction *I) { + SmallVector<const Value *, 4> Operands(I->value_op_begin(), + I->value_op_end()); + if (getUserCost(I, Operands) == TTI::TCC_Free) + return 0; + + if (isa<LoadInst>(I)) + return 4; + + Type *DstTy = I->getType(); + + // Usually an intrinsic is a simple instruction. + // A real function call is much slower. + if (auto *CI = dyn_cast<CallInst>(I)) { + const Function *F = CI->getCalledFunction(); + if (!F || static_cast<T *>(this)->isLoweredToCall(F)) + return 40; + // Some intrinsics return a value and a flag, we use the value type + // to decide its latency. + if (StructType* StructTy = dyn_cast<StructType>(DstTy)) + DstTy = StructTy->getElementType(0); + // Fall through to simple instructions. + } + + if (VectorType *VectorTy = dyn_cast<VectorType>(DstTy)) + DstTy = VectorTy->getElementType(); + if (DstTy->isFloatingPointTy()) + return 3; + + return 1; + } }; } |