| //===- llvm/Analysis/TargetTransformInfo.cpp ------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/Analysis/TargetTransformInfo.h" | |
| #include "llvm/ADT/SmallVector.h" | |
| #include "llvm/Analysis/CFG.h" | |
| #include "llvm/Analysis/LoopIterator.h" | |
| #include "llvm/Analysis/TargetLibraryInfo.h" | |
| #include "llvm/Analysis/TargetTransformInfoImpl.h" | |
| #include "llvm/IR/CFG.h" | |
| #include "llvm/IR/Dominators.h" | |
| #include "llvm/IR/Instruction.h" | |
| #include "llvm/IR/Instructions.h" | |
| #include "llvm/IR/IntrinsicInst.h" | |
| #include "llvm/IR/Module.h" | |
| #include "llvm/IR/Operator.h" | |
| #include "llvm/InitializePasses.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include <optional> | |
| #include <utility> | |
| using namespace llvm; | |
| using namespace PatternMatch; | |
| #define DEBUG_TYPE "tti" | |
| static cl::opt<bool> EnableReduxCost("costmodel-reduxcost", cl::init(false), | |
| cl::Hidden, | |
| cl::desc("Recognize reduction patterns.")); | |
| static cl::opt<unsigned> CacheLineSize( | |
| "cache-line-size", cl::init(0), cl::Hidden, | |
| cl::desc("Use this to override the target cache line size when " | |
| "specified by the user.")); | |
| static cl::opt<unsigned> MinPageSize( | |
| "min-page-size", cl::init(0), cl::Hidden, | |
| cl::desc("Use this to override the target's minimum page size.")); | |
| static cl::opt<unsigned> PredictableBranchThreshold( | |
| "predictable-branch-threshold", cl::init(99), cl::Hidden, | |
| cl::desc( | |
| "Use this to override the target's predictable branch threshold (%).")); | |
| namespace { | |
| /// No-op implementation of the TTI interface using the utility base | |
| /// classes. | |
| /// | |
| /// This is used when no target specific information is available. | |
| struct NoTTIImpl : TargetTransformInfoImplCRTPBase<NoTTIImpl> { | |
| explicit NoTTIImpl(const DataLayout &DL) | |
| : TargetTransformInfoImplCRTPBase<NoTTIImpl>(DL) {} | |
| }; | |
| } // namespace | |
| TargetTransformInfo::TargetTransformInfo( | |
| std::unique_ptr<const TargetTransformInfoImplBase> Impl) | |
| : TTIImpl(std::move(Impl)) {} | |
| bool HardwareLoopInfo::canAnalyze(LoopInfo &LI) { | |
| // If the loop has irreducible control flow, it can not be converted to | |
| // Hardware loop. | |
| LoopBlocksRPO RPOT(L); | |
| RPOT.perform(&LI); | |
| if (containsIrreducibleCFG<const BasicBlock *>(RPOT, LI)) | |
| return false; | |
| return true; | |
| } | |
| IntrinsicCostAttributes::IntrinsicCostAttributes( | |
| Intrinsic::ID Id, const CallBase &CI, InstructionCost ScalarizationCost, | |
| bool TypeBasedOnly) | |
| : II(dyn_cast<IntrinsicInst>(&CI)), RetTy(CI.getType()), IID(Id), | |
| ScalarizationCost(ScalarizationCost) { | |
| if (const auto *FPMO = dyn_cast<FPMathOperator>(&CI)) | |
| FMF = FPMO->getFastMathFlags(); | |
| if (!TypeBasedOnly) | |
| Arguments.insert(Arguments.begin(), CI.arg_begin(), CI.arg_end()); | |
| for (const Value *Arg : CI.args()) | |
| ParamTys.push_back(Arg->getType()); | |
| } | |
| IntrinsicCostAttributes::IntrinsicCostAttributes(Intrinsic::ID Id, Type *RTy, | |
| ArrayRef<Type *> Tys, | |
| FastMathFlags Flags, | |
| const IntrinsicInst *I, | |
| InstructionCost ScalarCost) | |
| : II(I), RetTy(RTy), IID(Id), FMF(Flags), ScalarizationCost(ScalarCost) { | |
| ParamTys.insert(ParamTys.begin(), Tys.begin(), Tys.end()); | |
| } | |
| IntrinsicCostAttributes::IntrinsicCostAttributes(Intrinsic::ID Id, Type *Ty, | |
| ArrayRef<const Value *> Args) | |
| : RetTy(Ty), IID(Id) { | |
| Arguments.insert(Arguments.begin(), Args.begin(), Args.end()); | |
| ParamTys.reserve(Arguments.size()); | |
| for (const Value *Argument : Arguments) | |
| ParamTys.push_back(Argument->getType()); | |
| } | |
| IntrinsicCostAttributes::IntrinsicCostAttributes( | |
| Intrinsic::ID Id, Type *RTy, ArrayRef<const Value *> Args, | |
| ArrayRef<Type *> Tys, FastMathFlags Flags, const IntrinsicInst *I, | |
| InstructionCost ScalarCost, VectorInstrContext VIC) | |
| : II(I), RetTy(RTy), IID(Id), FMF(Flags), ScalarizationCost(ScalarCost), | |
| VIC(VIC) { | |
| ParamTys.insert(ParamTys.begin(), Tys.begin(), Tys.end()); | |
| Arguments.insert(Arguments.begin(), Args.begin(), Args.end()); | |
| } | |
| HardwareLoopInfo::HardwareLoopInfo(Loop *L) : L(L) { | |
| // Match default options: | |
| // - hardware-loop-counter-bitwidth = 32 | |
| // - hardware-loop-decrement = 1 | |
| CountType = Type::getInt32Ty(L->getHeader()->getContext()); | |
| LoopDecrement = ConstantInt::get(CountType, 1); | |
| } | |
| bool HardwareLoopInfo::isHardwareLoopCandidate(ScalarEvolution &SE, | |
| LoopInfo &LI, DominatorTree &DT, | |
| bool ForceNestedLoop, | |
| bool ForceHardwareLoopPHI) { | |
| SmallVector<BasicBlock *, 4> ExitingBlocks; | |
| L->getExitingBlocks(ExitingBlocks); | |
| for (BasicBlock *BB : ExitingBlocks) { | |
| // If we pass the updated counter back through a phi, we need to know | |
| // which latch the updated value will be coming from. | |
| if (!L->isLoopLatch(BB)) { | |
| if (ForceHardwareLoopPHI || CounterInReg) | |
| continue; | |
| } | |
| const SCEV *EC = SE.getExitCount(L, BB); | |
| if (isa<SCEVCouldNotCompute>(EC)) | |
| continue; | |
| if (const SCEVConstant *ConstEC = dyn_cast<SCEVConstant>(EC)) { | |
| if (ConstEC->getValue()->isZero()) | |
| continue; | |
| } else if (!SE.isLoopInvariant(EC, L)) | |
| continue; | |
| if (SE.getTypeSizeInBits(EC->getType()) > CountType->getBitWidth()) | |
| continue; | |
| // If this exiting block is contained in a nested loop, it is not eligible | |
| // for insertion of the branch-and-decrement since the inner loop would | |
| // end up messing up the value in the CTR. | |
| if (!IsNestingLegal && LI.getLoopFor(BB) != L && !ForceNestedLoop) | |
| continue; | |
| // We now have a loop-invariant count of loop iterations (which is not the | |
| // constant zero) for which we know that this loop will not exit via this | |
| // existing block. | |
| // We need to make sure that this block will run on every loop iteration. | |
| // For this to be true, we must dominate all blocks with backedges. Such | |
| // blocks are in-loop predecessors to the header block. | |
| bool NotAlways = false; | |
| for (BasicBlock *Pred : predecessors(L->getHeader())) { | |
| if (!L->contains(Pred)) | |
| continue; | |
| if (!DT.dominates(BB, Pred)) { | |
| NotAlways = true; | |
| break; | |
| } | |
| } | |
| if (NotAlways) | |
| continue; | |
| // Make sure this blocks ends with a conditional branch. | |
| Instruction *TI = BB->getTerminator(); | |
| if (!TI) | |
| continue; | |
| if (CondBrInst *BI = dyn_cast<CondBrInst>(TI)) | |
| ExitBranch = BI; | |
| else | |
| continue; | |
| // Note that this block may not be the loop latch block, even if the loop | |
| // has a latch block. | |
| ExitBlock = BB; | |
| ExitCount = EC; | |
| break; | |
| } | |
| if (!ExitBlock) | |
| return false; | |
| return true; | |
| } | |
| TargetTransformInfo::TargetTransformInfo(const DataLayout &DL) | |
| : TTIImpl(std::make_unique<NoTTIImpl>(DL)) {} | |
| TargetTransformInfo::~TargetTransformInfo() = default; | |
| TargetTransformInfo::TargetTransformInfo(TargetTransformInfo &&Arg) | |
| : TTIImpl(std::move(Arg.TTIImpl)) {} | |
| TargetTransformInfo &TargetTransformInfo::operator=(TargetTransformInfo &&RHS) { | |
| TTIImpl = std::move(RHS.TTIImpl); | |
| return *this; | |
| } | |
| unsigned TargetTransformInfo::getInliningThresholdMultiplier() const { | |
| return TTIImpl->getInliningThresholdMultiplier(); | |
| } | |
| unsigned | |
| TargetTransformInfo::getInliningCostBenefitAnalysisSavingsMultiplier() const { | |
| return TTIImpl->getInliningCostBenefitAnalysisSavingsMultiplier(); | |
| } | |
| unsigned | |
| TargetTransformInfo::getInliningCostBenefitAnalysisProfitableMultiplier() | |
| const { | |
| return TTIImpl->getInliningCostBenefitAnalysisProfitableMultiplier(); | |
| } | |
| int TargetTransformInfo::getInliningLastCallToStaticBonus() const { | |
| return TTIImpl->getInliningLastCallToStaticBonus(); | |
| } | |
| unsigned | |
| TargetTransformInfo::adjustInliningThreshold(const CallBase *CB) const { | |
| return TTIImpl->adjustInliningThreshold(CB); | |
| } | |
| unsigned TargetTransformInfo::getCallerAllocaCost(const CallBase *CB, | |
| const AllocaInst *AI) const { | |
| return TTIImpl->getCallerAllocaCost(CB, AI); | |
| } | |
| int TargetTransformInfo::getInlinerVectorBonusPercent() const { | |
| return TTIImpl->getInlinerVectorBonusPercent(); | |
| } | |
| InstructionCost TargetTransformInfo::getGEPCost( | |
| Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands, | |
| TTI::TargetCostKind CostKind, Type *AccessType) const { | |
| return TTIImpl->getGEPCost(PointeeType, Ptr, Operands, CostKind, AccessType); | |
| } | |
| InstructionCost TargetTransformInfo::getPointersChainCost( | |
| ArrayRef<const Value *> Ptrs, const Value *Base, | |
| const TTI::PointersChainInfo &Info, Type *AccessTy, | |
| TTI::TargetCostKind CostKind) const { | |
| assert((Base || !Info.isSameBase()) && | |
| "If pointers have same base address it has to be provided."); | |
| return TTIImpl->getPointersChainCost(Ptrs, Base, Info, AccessTy, CostKind); | |
| } | |
| unsigned TargetTransformInfo::getEstimatedNumberOfCaseClusters( | |
| const SwitchInst &SI, unsigned &JTSize, ProfileSummaryInfo *PSI, | |
| BlockFrequencyInfo *BFI) const { | |
| return TTIImpl->getEstimatedNumberOfCaseClusters(SI, JTSize, PSI, BFI); | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getInstructionCost(const User *U, | |
| ArrayRef<const Value *> Operands, | |
| enum TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getInstructionCost(U, Operands, CostKind); | |
| assert((CostKind == TTI::TCK_RecipThroughput || Cost >= 0) && | |
| "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| BranchProbability TargetTransformInfo::getPredictableBranchThreshold() const { | |
| return PredictableBranchThreshold.getNumOccurrences() > 0 | |
| ? BranchProbability(PredictableBranchThreshold, 100) | |
| : TTIImpl->getPredictableBranchThreshold(); | |
| } | |
| InstructionCost TargetTransformInfo::getBranchMispredictPenalty() const { | |
| return TTIImpl->getBranchMispredictPenalty(); | |
| } | |
| bool TargetTransformInfo::hasBranchDivergence(const Function *F) const { | |
| return TTIImpl->hasBranchDivergence(F); | |
| } | |
| ValueUniformity | |
| llvm::TargetTransformInfo::getValueUniformity(const Value *V) const { | |
| ValueUniformity VU = TTIImpl->getValueUniformity(V); | |
| if (const auto *Call = dyn_cast<CallBase>(V)) { | |
| if (VU == ValueUniformity::NeverUniform && | |
| Call->hasFnAttr(Attribute::NoDivergenceSource)) | |
| return ValueUniformity::Default; | |
| } | |
| return VU; | |
| } | |
| bool llvm::TargetTransformInfo::isValidAddrSpaceCast(unsigned FromAS, | |
| unsigned ToAS) const { | |
| return TTIImpl->isValidAddrSpaceCast(FromAS, ToAS); | |
| } | |
| bool llvm::TargetTransformInfo::addrspacesMayAlias(unsigned FromAS, | |
| unsigned ToAS) const { | |
| return TTIImpl->addrspacesMayAlias(FromAS, ToAS); | |
| } | |
| unsigned TargetTransformInfo::getFlatAddressSpace() const { | |
| return TTIImpl->getFlatAddressSpace(); | |
| } | |
| unsigned TargetTransformInfo::getAddressSpaceJoin(unsigned AS1, | |
| unsigned AS2) const { | |
| assert(AS1 != AS2 && "Expected distinct address spaces"); | |
| return TTIImpl->getAddressSpaceJoin(AS1, AS2); | |
| } | |
| bool TargetTransformInfo::collectFlatAddressOperands( | |
| SmallVectorImpl<int> &OpIndexes, Intrinsic::ID IID) const { | |
| return TTIImpl->collectFlatAddressOperands(OpIndexes, IID); | |
| } | |
| bool TargetTransformInfo::isNoopAddrSpaceCast(unsigned FromAS, | |
| unsigned ToAS) const { | |
| return TTIImpl->isNoopAddrSpaceCast(FromAS, ToAS); | |
| } | |
| std::pair<KnownBits, KnownBits> | |
| TargetTransformInfo::computeKnownBitsAddrSpaceCast(unsigned ToAS, | |
| const Value &PtrOp) const { | |
| return TTIImpl->computeKnownBitsAddrSpaceCast(ToAS, PtrOp); | |
| } | |
| KnownBits TargetTransformInfo::computeKnownBitsAddrSpaceCast( | |
| unsigned FromAS, unsigned ToAS, const KnownBits &FromPtrBits) const { | |
| return TTIImpl->computeKnownBitsAddrSpaceCast(FromAS, ToAS, FromPtrBits); | |
| } | |
| APInt TargetTransformInfo::getAddrSpaceCastPreservedPtrMask( | |
| unsigned SrcAS, unsigned DstAS) const { | |
| return TTIImpl->getAddrSpaceCastPreservedPtrMask(SrcAS, DstAS); | |
| } | |
| bool TargetTransformInfo::canHaveNonUndefGlobalInitializerInAddressSpace( | |
| unsigned AS) const { | |
| return TTIImpl->canHaveNonUndefGlobalInitializerInAddressSpace(AS); | |
| } | |
| unsigned TargetTransformInfo::getAssumedAddrSpace(const Value *V) const { | |
| return TTIImpl->getAssumedAddrSpace(V); | |
| } | |
| std::pair<const Value *, unsigned> | |
| TargetTransformInfo::getPredicatedAddrSpace(const Value *V) const { | |
| return TTIImpl->getPredicatedAddrSpace(V); | |
| } | |
| Value *TargetTransformInfo::rewriteIntrinsicWithAddressSpace( | |
| IntrinsicInst *II, Value *OldV, Value *NewV) const { | |
| return TTIImpl->rewriteIntrinsicWithAddressSpace(II, OldV, NewV); | |
| } | |
| bool TargetTransformInfo::isLoweredToCall(const Function *F) const { | |
| return TTIImpl->isLoweredToCall(F); | |
| } | |
| bool TargetTransformInfo::isHardwareLoopProfitable( | |
| Loop *L, ScalarEvolution &SE, AssumptionCache &AC, | |
| TargetLibraryInfo *LibInfo, HardwareLoopInfo &HWLoopInfo) const { | |
| return TTIImpl->isHardwareLoopProfitable(L, SE, AC, LibInfo, HWLoopInfo); | |
| } | |
| unsigned TargetTransformInfo::getEpilogueVectorizationMinVF() const { | |
| return TTIImpl->getEpilogueVectorizationMinVF(); | |
| } | |
| bool TargetTransformInfo::preferTailFoldingOverEpilogue( | |
| TailFoldingInfo *TFI) const { | |
| return TTIImpl->preferTailFoldingOverEpilogue(TFI); | |
| } | |
| TailFoldingStyle TargetTransformInfo::getPreferredTailFoldingStyle() const { | |
| return TTIImpl->getPreferredTailFoldingStyle(); | |
| } | |
| std::optional<Instruction *> | |
| TargetTransformInfo::instCombineIntrinsic(InstCombiner &IC, | |
| IntrinsicInst &II) const { | |
| return TTIImpl->instCombineIntrinsic(IC, II); | |
| } | |
| std::optional<Value *> TargetTransformInfo::simplifyDemandedUseBitsIntrinsic( | |
| InstCombiner &IC, IntrinsicInst &II, APInt DemandedMask, KnownBits &Known, | |
| bool &KnownBitsComputed) const { | |
| return TTIImpl->simplifyDemandedUseBitsIntrinsic(IC, II, DemandedMask, Known, | |
| KnownBitsComputed); | |
| } | |
| std::optional<Value *> TargetTransformInfo::simplifyDemandedVectorEltsIntrinsic( | |
| InstCombiner &IC, IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, | |
| APInt &UndefElts2, APInt &UndefElts3, | |
| std::function<void(Instruction *, unsigned, APInt, APInt &)> | |
| SimplifyAndSetOp) const { | |
| return TTIImpl->simplifyDemandedVectorEltsIntrinsic( | |
| IC, II, DemandedElts, UndefElts, UndefElts2, UndefElts3, | |
| SimplifyAndSetOp); | |
| } | |
| void TargetTransformInfo::getUnrollingPreferences( | |
| Loop *L, ScalarEvolution &SE, UnrollingPreferences &UP, | |
| OptimizationRemarkEmitter *ORE) const { | |
| return TTIImpl->getUnrollingPreferences(L, SE, UP, ORE); | |
| } | |
| void TargetTransformInfo::getPeelingPreferences(Loop *L, ScalarEvolution &SE, | |
| PeelingPreferences &PP) const { | |
| return TTIImpl->getPeelingPreferences(L, SE, PP); | |
| } | |
| bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const { | |
| return TTIImpl->isLegalAddImmediate(Imm); | |
| } | |
| bool TargetTransformInfo::isLegalAddScalableImmediate(int64_t Imm) const { | |
| return TTIImpl->isLegalAddScalableImmediate(Imm); | |
| } | |
| bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const { | |
| return TTIImpl->isLegalICmpImmediate(Imm); | |
| } | |
| bool TargetTransformInfo::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, | |
| int64_t BaseOffset, | |
| bool HasBaseReg, int64_t Scale, | |
| unsigned AddrSpace, | |
| Instruction *I, | |
| int64_t ScalableOffset) const { | |
| return TTIImpl->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, | |
| Scale, AddrSpace, I, ScalableOffset); | |
| } | |
| bool TargetTransformInfo::isLSRCostLess(const LSRCost &C1, | |
| const LSRCost &C2) const { | |
| return TTIImpl->isLSRCostLess(C1, C2); | |
| } | |
| bool TargetTransformInfo::isNumRegsMajorCostOfLSR() const { | |
| return TTIImpl->isNumRegsMajorCostOfLSR(); | |
| } | |
| bool TargetTransformInfo::shouldDropLSRSolutionIfLessProfitable() const { | |
| return TTIImpl->shouldDropLSRSolutionIfLessProfitable(); | |
| } | |
| bool TargetTransformInfo::isProfitableLSRChainElement(Instruction *I) const { | |
| return TTIImpl->isProfitableLSRChainElement(I); | |
| } | |
| bool TargetTransformInfo::canMacroFuseCmp() const { | |
| return TTIImpl->canMacroFuseCmp(); | |
| } | |
| bool TargetTransformInfo::canSaveCmp(Loop *L, CondBrInst **BI, | |
| ScalarEvolution *SE, LoopInfo *LI, | |
| DominatorTree *DT, AssumptionCache *AC, | |
| TargetLibraryInfo *LibInfo) const { | |
| return TTIImpl->canSaveCmp(L, BI, SE, LI, DT, AC, LibInfo); | |
| } | |
| TTI::AddressingModeKind | |
| TargetTransformInfo::getPreferredAddressingMode(const Loop *L, | |
| ScalarEvolution *SE) const { | |
| return TTIImpl->getPreferredAddressingMode(L, SE); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedStore(Type *DataType, Align Alignment, | |
| unsigned AddressSpace, | |
| TTI::MaskKind MaskKind) const { | |
| return TTIImpl->isLegalMaskedStore(DataType, Alignment, AddressSpace, | |
| MaskKind); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedLoad(Type *DataType, Align Alignment, | |
| unsigned AddressSpace, | |
| TTI::MaskKind MaskKind) const { | |
| return TTIImpl->isLegalMaskedLoad(DataType, Alignment, AddressSpace, | |
| MaskKind); | |
| } | |
| bool TargetTransformInfo::isLegalSpeculativeLoad(Type *DataType, | |
| unsigned AddressSpace) const { | |
| return TTIImpl->isLegalSpeculativeLoad(DataType, AddressSpace); | |
| } | |
| bool TargetTransformInfo::isLegalNTStore(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalNTStore(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalNTLoad(Type *DataType, Align Alignment) const { | |
| return TTIImpl->isLegalNTLoad(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalBroadcastLoad(Type *ElementTy, | |
| ElementCount NumElements) const { | |
| return TTIImpl->isLegalBroadcastLoad(ElementTy, NumElements); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedGather(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalMaskedGather(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalAltInstr( | |
| VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, | |
| const SmallBitVector &OpcodeMask) const { | |
| return TTIImpl->isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedScatter(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalMaskedScatter(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::forceScalarizeMaskedGather(VectorType *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->forceScalarizeMaskedGather(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::forceScalarizeMaskedScatter(VectorType *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->forceScalarizeMaskedScatter(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedCompressStore(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalMaskedCompressStore(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedExpandLoad(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalMaskedExpandLoad(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalStridedLoadStore(Type *DataType, | |
| Align Alignment) const { | |
| return TTIImpl->isLegalStridedLoadStore(DataType, Alignment); | |
| } | |
| bool TargetTransformInfo::isLegalInterleavedAccessType( | |
| VectorType *VTy, unsigned Factor, Align Alignment, | |
| unsigned AddrSpace) const { | |
| return TTIImpl->isLegalInterleavedAccessType(VTy, Factor, Alignment, | |
| AddrSpace); | |
| } | |
| bool TargetTransformInfo::isLegalMaskedVectorHistogram(Type *AddrType, | |
| Type *DataType) const { | |
| return TTIImpl->isLegalMaskedVectorHistogram(AddrType, DataType); | |
| } | |
| bool TargetTransformInfo::enableOrderedReductions() const { | |
| return TTIImpl->enableOrderedReductions(); | |
| } | |
| bool TargetTransformInfo::hasDivRemOp(Type *DataType, bool IsSigned) const { | |
| return TTIImpl->hasDivRemOp(DataType, IsSigned); | |
| } | |
| bool TargetTransformInfo::hasVolatileVariant(Instruction *I, | |
| unsigned AddrSpace) const { | |
| return TTIImpl->hasVolatileVariant(I, AddrSpace); | |
| } | |
| bool TargetTransformInfo::prefersVectorizedAddressing() const { | |
| return TTIImpl->prefersVectorizedAddressing(); | |
| } | |
| InstructionCost TargetTransformInfo::getScalingFactorCost( | |
| Type *Ty, GlobalValue *BaseGV, StackOffset BaseOffset, bool HasBaseReg, | |
| int64_t Scale, unsigned AddrSpace) const { | |
| InstructionCost Cost = TTIImpl->getScalingFactorCost( | |
| Ty, BaseGV, BaseOffset, HasBaseReg, Scale, AddrSpace); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| bool TargetTransformInfo::LSRWithInstrQueries() const { | |
| return TTIImpl->LSRWithInstrQueries(); | |
| } | |
| bool TargetTransformInfo::isTruncateFree(Type *Ty1, Type *Ty2) const { | |
| return TTIImpl->isTruncateFree(Ty1, Ty2); | |
| } | |
| bool TargetTransformInfo::isProfitableToHoist(Instruction *I) const { | |
| return TTIImpl->isProfitableToHoist(I); | |
| } | |
| bool TargetTransformInfo::useAA() const { return TTIImpl->useAA(); } | |
| bool TargetTransformInfo::isTypeLegal(Type *Ty) const { | |
| return TTIImpl->isTypeLegal(Ty); | |
| } | |
| unsigned TargetTransformInfo::getRegUsageForType(Type *Ty) const { | |
| return TTIImpl->getRegUsageForType(Ty); | |
| } | |
| bool TargetTransformInfo::shouldBuildLookupTables() const { | |
| return TTIImpl->shouldBuildLookupTables(); | |
| } | |
| bool TargetTransformInfo::shouldBuildLookupTablesForConstant( | |
| Constant *C) const { | |
| return TTIImpl->shouldBuildLookupTablesForConstant(C); | |
| } | |
| unsigned TargetTransformInfo::getMinimumLookupTableEntryBitWidth() const { | |
| return TTIImpl->getMinimumLookupTableEntryBitWidth(); | |
| } | |
| bool TargetTransformInfo::shouldBuildRelLookupTables() const { | |
| return TTIImpl->shouldBuildRelLookupTables(); | |
| } | |
| bool TargetTransformInfo::useColdCCForColdCall(Function &F) const { | |
| return TTIImpl->useColdCCForColdCall(F); | |
| } | |
| bool TargetTransformInfo::useFastCCForInternalCall(Function &F) const { | |
| return TTIImpl->useFastCCForInternalCall(F); | |
| } | |
| bool TargetTransformInfo::isTargetIntrinsicWithScalarOpAtArg( | |
| Intrinsic::ID ID, unsigned ScalarOpdIdx) const { | |
| return TTIImpl->isTargetIntrinsicWithScalarOpAtArg(ID, ScalarOpdIdx); | |
| } | |
| bool TargetTransformInfo::isTargetIntrinsicWithOverloadTypeAtArg( | |
| Intrinsic::ID ID, int OpdIdx) const { | |
| return TTIImpl->isTargetIntrinsicWithOverloadTypeAtArg(ID, OpdIdx); | |
| } | |
| bool TargetTransformInfo::isTargetIntrinsicWithStructReturnOverloadAtField( | |
| Intrinsic::ID ID, int RetIdx) const { | |
| return TTIImpl->isTargetIntrinsicWithStructReturnOverloadAtField(ID, RetIdx); | |
| } | |
| TargetTransformInfo::VectorInstrContext | |
| TargetTransformInfo::combineVectorInstrContexts( | |
| TargetTransformInfo::VectorInstrContext Ctx1, | |
| TargetTransformInfo::VectorInstrContext Ctx2) { | |
| return Ctx1 == Ctx2 ? Ctx1 : TargetTransformInfo::VectorInstrContext::None; | |
| } | |
| TargetTransformInfo::VectorInstrContext | |
| TargetTransformInfo::getVectorInstrContextHint(const Instruction *I) { | |
| if (!I) | |
| return VectorInstrContext::None; | |
| // For inserts, check if the value being inserted comes from a single-use | |
| // load. | |
| if (isa<InsertElementInst>(I) && isa<LoadInst>(I->getOperand(1)) && | |
| I->getOperand(1)->hasOneUse()) | |
| return VectorInstrContext::Load; | |
| // For extracts, check if it has a single use that is a store. | |
| if (isa<ExtractElementInst>(I) && I->hasOneUse() && | |
| isa<StoreInst>(*I->user_begin())) | |
| return VectorInstrContext::Store; | |
| return VectorInstrContext::None; | |
| } | |
| TargetTransformInfo::VectorInstrContext | |
| TargetTransformInfo::getBuildVectorContextHint( | |
| ArrayRef<int> Mask, ArrayRef<Value *> Scalars, | |
| function_ref<bool(SmallVectorImpl<BuildVectorUseOp> &)> GatherUseOps) | |
| const { | |
| return TTIImpl->getBuildVectorContextHint(Mask, Scalars, GatherUseOps); | |
| } | |
| InstructionCost TargetTransformInfo::getScalarizationOverhead( | |
| VectorType *Ty, const APInt &DemandedElts, bool Insert, bool Extract, | |
| TTI::TargetCostKind CostKind, bool ForPoisonSrc, ArrayRef<Value *> VL, | |
| TTI::VectorInstrContext VIC) const { | |
| return TTIImpl->getScalarizationOverhead(Ty, DemandedElts, Insert, Extract, | |
| CostKind, ForPoisonSrc, VL, VIC); | |
| } | |
| InstructionCost TargetTransformInfo::getOperandsScalarizationOverhead( | |
| ArrayRef<Type *> Tys, TTI::TargetCostKind CostKind, | |
| TTI::VectorInstrContext VIC) const { | |
| return TTIImpl->getOperandsScalarizationOverhead(Tys, CostKind, VIC); | |
| } | |
| bool TargetTransformInfo::supportsEfficientVectorElementLoadStore() const { | |
| return TTIImpl->supportsEfficientVectorElementLoadStore(); | |
| } | |
| bool TargetTransformInfo::supportsTailCalls() const { | |
| return TTIImpl->supportsTailCalls(); | |
| } | |
| bool TargetTransformInfo::supportsTailCallFor(const CallBase *CB) const { | |
| return TTIImpl->supportsTailCallFor(CB); | |
| } | |
| bool TargetTransformInfo::enableAggressiveInterleaving( | |
| bool LoopHasReductions) const { | |
| return TTIImpl->enableAggressiveInterleaving(LoopHasReductions); | |
| } | |
| TargetTransformInfo::MemCmpExpansionOptions | |
| TargetTransformInfo::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const { | |
| return TTIImpl->enableMemCmpExpansion(OptSize, IsZeroCmp); | |
| } | |
| bool TargetTransformInfo::enableSelectOptimize() const { | |
| return TTIImpl->enableSelectOptimize(); | |
| } | |
| bool TargetTransformInfo::shouldTreatInstructionLikeSelect( | |
| const Instruction *I) const { | |
| return TTIImpl->shouldTreatInstructionLikeSelect(I); | |
| } | |
| bool TargetTransformInfo::enableInterleavedAccessVectorization() const { | |
| return TTIImpl->enableInterleavedAccessVectorization(); | |
| } | |
| bool TargetTransformInfo::enableMaskedInterleavedAccessVectorization() const { | |
| return TTIImpl->enableMaskedInterleavedAccessVectorization(); | |
| } | |
| bool TargetTransformInfo::isFPVectorizationPotentiallyUnsafe() const { | |
| return TTIImpl->isFPVectorizationPotentiallyUnsafe(); | |
| } | |
| bool | |
| TargetTransformInfo::allowsMisalignedMemoryAccesses(LLVMContext &Context, | |
| unsigned BitWidth, | |
| unsigned AddressSpace, | |
| Align Alignment, | |
| unsigned *Fast) const { | |
| return TTIImpl->allowsMisalignedMemoryAccesses(Context, BitWidth, | |
| AddressSpace, Alignment, Fast); | |
| } | |
| TargetTransformInfo::PopcntSupportKind | |
| TargetTransformInfo::getPopcntSupport(unsigned IntTyWidthInBit) const { | |
| return TTIImpl->getPopcntSupport(IntTyWidthInBit); | |
| } | |
| bool TargetTransformInfo::haveFastSqrt(Type *Ty) const { | |
| return TTIImpl->haveFastSqrt(Ty); | |
| } | |
| bool TargetTransformInfo::haveFastClmul(IntegerType *Ty) const { | |
| return TTIImpl->haveFastClmul(Ty); | |
| } | |
| bool TargetTransformInfo::isExpensiveToSpeculativelyExecute( | |
| const Instruction *I) const { | |
| return TTIImpl->isExpensiveToSpeculativelyExecute(I); | |
| } | |
| bool TargetTransformInfo::isFCmpOrdCheaperThanFCmpZero(Type *Ty) const { | |
| return TTIImpl->isFCmpOrdCheaperThanFCmpZero(Ty); | |
| } | |
| InstructionCost TargetTransformInfo::getFPOpCost(Type *Ty) const { | |
| InstructionCost Cost = TTIImpl->getFPOpCost(Ty); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getIntImmCodeSizeCost(unsigned Opcode, | |
| unsigned Idx, | |
| const APInt &Imm, | |
| Type *Ty) const { | |
| InstructionCost Cost = TTIImpl->getIntImmCodeSizeCost(Opcode, Idx, Imm, Ty); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getIntImmCost(Imm, Ty, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getIntImmCostInst( | |
| unsigned Opcode, unsigned Idx, const APInt &Imm, Type *Ty, | |
| TTI::TargetCostKind CostKind, Instruction *Inst) const { | |
| InstructionCost Cost = | |
| TTIImpl->getIntImmCostInst(Opcode, Idx, Imm, Ty, CostKind, Inst); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getIntImmCostIntrin(Intrinsic::ID IID, unsigned Idx, | |
| const APInt &Imm, Type *Ty, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getIntImmCostIntrin(IID, Idx, Imm, Ty, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| bool TargetTransformInfo::preferToKeepConstantsAttached( | |
| const Instruction &Inst, const Function &Fn) const { | |
| return TTIImpl->preferToKeepConstantsAttached(Inst, Fn); | |
| } | |
| unsigned TargetTransformInfo::getNumberOfRegisters(unsigned ClassID) const { | |
| return TTIImpl->getNumberOfRegisters(ClassID); | |
| } | |
| bool TargetTransformInfo::hasConditionalLoadStoreForType(Type *Ty, | |
| bool IsStore) const { | |
| return TTIImpl->hasConditionalLoadStoreForType(Ty, IsStore); | |
| } | |
| unsigned TargetTransformInfo::getRegisterClassForType(bool Vector, | |
| Type *Ty) const { | |
| return TTIImpl->getRegisterClassForType(Vector, Ty); | |
| } | |
| const char *TargetTransformInfo::getRegisterClassName(unsigned ClassID) const { | |
| return TTIImpl->getRegisterClassName(ClassID); | |
| } | |
| InstructionCost TargetTransformInfo::getRegisterClassSpillCost( | |
| unsigned ClassID, TTI::TargetCostKind CostKind) const { | |
| return TTIImpl->getRegisterClassSpillCost(ClassID, CostKind); | |
| } | |
| InstructionCost TargetTransformInfo::getRegisterClassReloadCost( | |
| unsigned ClassID, TTI::TargetCostKind CostKind) const { | |
| return TTIImpl->getRegisterClassReloadCost(ClassID, CostKind); | |
| } | |
| TypeSize TargetTransformInfo::getRegisterBitWidth( | |
| TargetTransformInfo::RegisterKind K) const { | |
| return TTIImpl->getRegisterBitWidth(K); | |
| } | |
| unsigned TargetTransformInfo::getMinVectorRegisterBitWidth() const { | |
| return TTIImpl->getMinVectorRegisterBitWidth(); | |
| } | |
| std::optional<unsigned> TargetTransformInfo::getVScaleForTuning() const { | |
| return TTIImpl->getVScaleForTuning(); | |
| } | |
| bool TargetTransformInfo::shouldMaximizeVectorBandwidth( | |
| TargetTransformInfo::RegisterKind K) const { | |
| return TTIImpl->shouldMaximizeVectorBandwidth(K); | |
| } | |
| ElementCount TargetTransformInfo::getMinimumVF(unsigned ElemWidth, | |
| bool IsScalable) const { | |
| return TTIImpl->getMinimumVF(ElemWidth, IsScalable); | |
| } | |
| unsigned TargetTransformInfo::getMaximumVF(unsigned ElemWidth, | |
| unsigned Opcode) const { | |
| return TTIImpl->getMaximumVF(ElemWidth, Opcode); | |
| } | |
| unsigned TargetTransformInfo::getStoreMinimumVF(unsigned VF, Type *ScalarMemTy, | |
| Type *ScalarValTy, | |
| Align Alignment, | |
| unsigned AddrSpace) const { | |
| return TTIImpl->getStoreMinimumVF(VF, ScalarMemTy, ScalarValTy, Alignment, | |
| AddrSpace); | |
| } | |
| bool TargetTransformInfo::shouldConsiderAddressTypePromotion( | |
| const Instruction &I, bool &AllowPromotionWithoutCommonHeader) const { | |
| return TTIImpl->shouldConsiderAddressTypePromotion( | |
| I, AllowPromotionWithoutCommonHeader); | |
| } | |
| unsigned TargetTransformInfo::getCacheLineSize() const { | |
| return CacheLineSize.getNumOccurrences() > 0 ? CacheLineSize | |
| : TTIImpl->getCacheLineSize(); | |
| } | |
| std::optional<unsigned> | |
| TargetTransformInfo::getCacheSize(CacheLevel Level) const { | |
| return TTIImpl->getCacheSize(Level); | |
| } | |
| std::optional<unsigned> | |
| TargetTransformInfo::getCacheAssociativity(CacheLevel Level) const { | |
| return TTIImpl->getCacheAssociativity(Level); | |
| } | |
| std::optional<unsigned> TargetTransformInfo::getMinPageSize() const { | |
| return MinPageSize.getNumOccurrences() > 0 ? MinPageSize | |
| : TTIImpl->getMinPageSize(); | |
| } | |
| unsigned TargetTransformInfo::getPrefetchDistance() const { | |
| return TTIImpl->getPrefetchDistance(); | |
| } | |
| unsigned TargetTransformInfo::getMinPrefetchStride( | |
| unsigned NumMemAccesses, unsigned NumStridedMemAccesses, | |
| unsigned NumPrefetches, bool HasCall) const { | |
| return TTIImpl->getMinPrefetchStride(NumMemAccesses, NumStridedMemAccesses, | |
| NumPrefetches, HasCall); | |
| } | |
| unsigned TargetTransformInfo::getMaxPrefetchIterationsAhead() const { | |
| return TTIImpl->getMaxPrefetchIterationsAhead(); | |
| } | |
| bool TargetTransformInfo::enableWritePrefetching() const { | |
| return TTIImpl->enableWritePrefetching(); | |
| } | |
| bool TargetTransformInfo::shouldPrefetchAddressSpace(unsigned AS) const { | |
| return TTIImpl->shouldPrefetchAddressSpace(AS); | |
| } | |
| InstructionCost TargetTransformInfo::getPartialReductionCost( | |
| unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, | |
| ElementCount VF, PartialReductionExtendKind OpAExtend, | |
| PartialReductionExtendKind OpBExtend, std::optional<unsigned> BinOp, | |
| TTI::TargetCostKind CostKind, std::optional<FastMathFlags> FMF) const { | |
| return TTIImpl->getPartialReductionCost(Opcode, InputTypeA, InputTypeB, | |
| AccumType, VF, OpAExtend, OpBExtend, | |
| BinOp, CostKind, FMF); | |
| } | |
| unsigned | |
| TargetTransformInfo::getMaxInterleaveFactor(ElementCount VF, | |
| bool HasUnorderedReductions) const { | |
| return TTIImpl->getMaxInterleaveFactor(VF, HasUnorderedReductions); | |
| } | |
| TargetTransformInfo::OperandValueInfo | |
| TargetTransformInfo::getOperandInfo(const Value *V) { | |
| OperandValueKind OpInfo = OK_AnyValue; | |
| OperandValueProperties OpProps = OP_None; | |
| // undef/poison don't materialize constants. | |
| if (isa<UndefValue>(V)) | |
| return {OK_AnyValue, OP_None}; | |
| if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) { | |
| if (const auto *CI = dyn_cast<ConstantInt>(V)) { | |
| if (CI->getValue().isPowerOf2()) | |
| OpProps = OP_PowerOf2; | |
| else if (CI->getValue().isNegatedPowerOf2()) | |
| OpProps = OP_NegatedPowerOf2; | |
| } | |
| return {OK_UniformConstantValue, OpProps}; | |
| } | |
| // A broadcast shuffle creates a uniform value. | |
| // TODO: Add support for non-zero index broadcasts. | |
| // TODO: Add support for different source vector width. | |
| if (const auto *ShuffleInst = dyn_cast<ShuffleVectorInst>(V)) | |
| if (ShuffleInst->isZeroEltSplat()) | |
| OpInfo = OK_UniformValue; | |
| const Value *Splat = getSplatValue(V); | |
| // Check for a splat of a constant or for a non uniform vector of constants | |
| // and check if the constant(s) are all powers of two. | |
| if (Splat) { | |
| // Check for a splat of a uniform value. This is not loop aware, so return | |
| // true only for the obviously uniform cases (argument, globalvalue) | |
| if (isa<Argument>(Splat) || isa<GlobalValue>(Splat)) { | |
| OpInfo = OK_UniformValue; | |
| } else if (isa<Constant>(Splat)) { | |
| OpInfo = OK_UniformConstantValue; | |
| if (auto *CI = dyn_cast<ConstantInt>(Splat)) { | |
| if (CI->getValue().isPowerOf2()) | |
| OpProps = OP_PowerOf2; | |
| else if (CI->getValue().isNegatedPowerOf2()) | |
| OpProps = OP_NegatedPowerOf2; | |
| } | |
| } | |
| } else if (const auto *CDS = dyn_cast<ConstantDataSequential>(V)) { | |
| OpInfo = OK_NonUniformConstantValue; | |
| bool AllPow2 = true, AllNegPow2 = true; | |
| for (uint64_t I = 0, E = CDS->getNumElements(); I != E; ++I) { | |
| if (auto *CI = dyn_cast<ConstantInt>(CDS->getElementAsConstant(I))) { | |
| AllPow2 &= CI->getValue().isPowerOf2(); | |
| AllNegPow2 &= CI->getValue().isNegatedPowerOf2(); | |
| if (AllPow2 || AllNegPow2) | |
| continue; | |
| } | |
| AllPow2 = AllNegPow2 = false; | |
| break; | |
| } | |
| OpProps = AllPow2 ? OP_PowerOf2 : OpProps; | |
| OpProps = AllNegPow2 ? OP_NegatedPowerOf2 : OpProps; | |
| } else if (isa<ConstantVector>(V) || isa<ConstantDataVector>(V)) { | |
| OpInfo = OK_NonUniformConstantValue; | |
| } | |
| return {OpInfo, OpProps}; | |
| } | |
| TargetTransformInfo::OperandValueInfo | |
| TargetTransformInfo::commonOperandInfo(const Value *X, const Value *Y) { | |
| OperandValueInfo OpInfoX = getOperandInfo(X); | |
| if (X == Y) | |
| return OpInfoX; | |
| return OpInfoX.mergeWith(getOperandInfo(Y)); | |
| } | |
| InstructionCost TargetTransformInfo::getArithmeticInstrCost( | |
| unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, | |
| OperandValueInfo Op1Info, OperandValueInfo Op2Info, | |
| ArrayRef<const Value *> Args, const Instruction *CtxI, | |
| const TargetLibraryInfo *TLibInfo) const { | |
| // Use call cost for frem intructions that have platform specific vector math | |
| // functions, as those will be replaced with calls later by SelectionDAG or | |
| // ReplaceWithVecLib pass. | |
| if (TLibInfo && Opcode == Instruction::FRem) { | |
| VectorType *VecTy = dyn_cast<VectorType>(Ty); | |
| LibFunc Func = TLibInfo->getLibFunc(Instruction::FRem, Ty->getScalarType()); | |
| if (VecTy && Func != NotLibFunc && | |
| TLibInfo->isFunctionVectorizable(TLibInfo->getName(Func), | |
| VecTy->getElementCount())) | |
| return getCallInstrCost(nullptr, VecTy, {VecTy, VecTy}, CostKind); | |
| } | |
| InstructionCost Cost = TTIImpl->getArithmeticInstrCost( | |
| Opcode, Ty, CostKind, Op1Info, Op2Info, Args, CtxI); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getAltInstrCost( | |
| VectorType *VecTy, unsigned Opcode0, unsigned Opcode1, | |
| const SmallBitVector &OpcodeMask, TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getAltInstrCost(VecTy, Opcode0, Opcode1, OpcodeMask, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getShuffleCost( | |
| ShuffleKind Kind, VectorType *DstTy, VectorType *SrcTy, | |
| TTI::TargetCostKind CostKind, ArrayRef<int> Mask, int Index, | |
| VectorType *SubTp, ArrayRef<const Value *> Args, const Instruction *CtxI, | |
| TTI::VectorInstrContext VIC) const { | |
| assert((Mask.empty() || DstTy->isScalableTy() || | |
| Mask.size() == DstTy->getElementCount().getKnownMinValue()) && | |
| "Expected the Mask to match the return size if given"); | |
| assert(SrcTy->getScalarType() == DstTy->getScalarType() && | |
| "Expected the same scalar types"); | |
| InstructionCost Cost = TTIImpl->getShuffleCost( | |
| Kind, DstTy, SrcTy, CostKind, Mask, Index, SubTp, Args, CtxI, VIC); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| TargetTransformInfo::PartialReductionExtendKind | |
| TargetTransformInfo::getPartialReductionExtendKind(Instruction *I) { | |
| if (auto *Cast = dyn_cast<CastInst>(I)) | |
| return getPartialReductionExtendKind(Cast->getOpcode()); | |
| return PR_None; | |
| } | |
| Instruction::CastOps | |
| TargetTransformInfo::getOpcodeForPartialReductionExtendKind( | |
| TargetTransformInfo::PartialReductionExtendKind Kind) { | |
| switch (Kind) { | |
| case TargetTransformInfo::PR_ZeroExtend: | |
| return Instruction::CastOps::ZExt; | |
| case TargetTransformInfo::PR_SignExtend: | |
| return Instruction::CastOps::SExt; | |
| case TargetTransformInfo::PR_FPExtend: | |
| return Instruction::CastOps::FPExt; | |
| default: | |
| break; | |
| } | |
| llvm_unreachable("Unhandled partial reduction extend kind"); | |
| } | |
| TargetTransformInfo::PartialReductionExtendKind | |
| TargetTransformInfo::getPartialReductionExtendKind( | |
| Instruction::CastOps CastOpc) { | |
| switch (CastOpc) { | |
| case Instruction::CastOps::ZExt: | |
| return PR_ZeroExtend; | |
| case Instruction::CastOps::SExt: | |
| return PR_SignExtend; | |
| case Instruction::CastOps::FPExt: | |
| return PR_FPExtend; | |
| default: | |
| return PR_None; | |
| } | |
| llvm_unreachable("Unhandled cast opcode"); | |
| } | |
| TTI::CastContextHint | |
| TargetTransformInfo::getCastContextHint(const Instruction *I) { | |
| if (!I) | |
| return CastContextHint::None; | |
| auto getLoadStoreKind = [](const Value *V, unsigned LdStOp, unsigned MaskedOp, | |
| unsigned GatScatOp) { | |
| const Instruction *I = dyn_cast<Instruction>(V); | |
| if (!I) | |
| return CastContextHint::None; | |
| if (I->getOpcode() == LdStOp) | |
| return CastContextHint::Normal; | |
| if (const IntrinsicInst *II = dyn_cast<IntrinsicInst>(I)) { | |
| if (II->getIntrinsicID() == MaskedOp) | |
| return TTI::CastContextHint::Masked; | |
| if (II->getIntrinsicID() == GatScatOp) | |
| return TTI::CastContextHint::GatherScatter; | |
| } | |
| return TTI::CastContextHint::None; | |
| }; | |
| switch (I->getOpcode()) { | |
| case Instruction::ZExt: | |
| case Instruction::SExt: | |
| case Instruction::FPExt: | |
| return getLoadStoreKind(I->getOperand(0), Instruction::Load, | |
| Intrinsic::masked_load, Intrinsic::masked_gather); | |
| case Instruction::Trunc: | |
| case Instruction::FPTrunc: | |
| if (I->hasOneUse()) | |
| return getLoadStoreKind(*I->user_begin(), Instruction::Store, | |
| Intrinsic::masked_store, | |
| Intrinsic::masked_scatter); | |
| break; | |
| default: | |
| return CastContextHint::None; | |
| } | |
| return TTI::CastContextHint::None; | |
| } | |
| InstructionCost TargetTransformInfo::getCastInstrCost( | |
| unsigned Opcode, Type *Dst, Type *Src, CastContextHint CCH, | |
| TTI::TargetCostKind CostKind, const Instruction *I) const { | |
| assert((I == nullptr || I->getOpcode() == Opcode) && | |
| "Opcode should reflect passed instruction."); | |
| InstructionCost Cost = | |
| TTIImpl->getCastInstrCost(Opcode, Dst, Src, CCH, CostKind, I); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getExtractWithExtendCost( | |
| unsigned Opcode, Type *Dst, VectorType *VecTy, unsigned Index, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getExtractWithExtendCost(Opcode, Dst, VecTy, Index, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getCFInstrCost( | |
| unsigned Opcode, TTI::TargetCostKind CostKind, const Instruction *I) const { | |
| assert((I == nullptr || I->getOpcode() == Opcode) && | |
| "Opcode should reflect passed instruction."); | |
| InstructionCost Cost = TTIImpl->getCFInstrCost(Opcode, CostKind, I); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getCmpSelInstrCost( | |
| unsigned Opcode, Type *ValTy, Type *CondTy, CmpInst::Predicate VecPred, | |
| TTI::TargetCostKind CostKind, OperandValueInfo Op1Info, | |
| OperandValueInfo Op2Info, const Instruction *I) const { | |
| assert((I == nullptr || I->getOpcode() == Opcode) && | |
| "Opcode should reflect passed instruction."); | |
| InstructionCost Cost = TTIImpl->getCmpSelInstrCost( | |
| Opcode, ValTy, CondTy, VecPred, CostKind, Op1Info, Op2Info, I); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getVectorInstrCost( | |
| unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, | |
| const Value *Op0, const Value *Op1, TTI::VectorInstrContext VIC) const { | |
| assert((Opcode == Instruction::InsertElement || | |
| Opcode == Instruction::ExtractElement) && | |
| "Expecting Opcode to be insertelement/extractelement."); | |
| InstructionCost Cost = | |
| TTIImpl->getVectorInstrCost(Opcode, Val, CostKind, Index, Op0, Op1, VIC); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getVectorInstrCost( | |
| unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, unsigned Index, | |
| Value *Scalar, ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx, | |
| TTI::VectorInstrContext VIC) const { | |
| assert((Opcode == Instruction::InsertElement || | |
| Opcode == Instruction::ExtractElement) && | |
| "Expecting Opcode to be insertelement/extractelement."); | |
| InstructionCost Cost = TTIImpl->getVectorInstrCost( | |
| Opcode, Val, CostKind, Index, Scalar, ScalarUserAndIdx, VIC); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getVectorInstrCost( | |
| const Instruction &I, Type *Val, TTI::TargetCostKind CostKind, | |
| unsigned Index, TTI::VectorInstrContext VIC) const { | |
| // FIXME: Assert that Opcode is either InsertElement or ExtractElement. | |
| // This is mentioned in the interface description and respected by all | |
| // callers, but never asserted upon. | |
| InstructionCost Cost = | |
| TTIImpl->getVectorInstrCost(I, Val, CostKind, Index, VIC); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getIndexedVectorInstrCostFromEnd( | |
| unsigned Opcode, Type *Val, TTI::TargetCostKind CostKind, | |
| unsigned Index) const { | |
| InstructionCost Cost = | |
| TTIImpl->getIndexedVectorInstrCostFromEnd(Opcode, Val, CostKind, Index); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getInsertExtractValueCost( | |
| unsigned Opcode, TTI::TargetCostKind CostKind) const { | |
| assert((Opcode == Instruction::InsertValue || | |
| Opcode == Instruction::ExtractValue) && | |
| "Expecting Opcode to be insertvalue/extractvalue."); | |
| InstructionCost Cost = TTIImpl->getInsertExtractValueCost(Opcode, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getReplicationShuffleCost( | |
| Type *EltTy, int ReplicationFactor, int VF, const APInt &DemandedDstElts, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getReplicationShuffleCost( | |
| EltTy, ReplicationFactor, VF, DemandedDstElts, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getMemoryOpCost( | |
| unsigned Opcode, Type *Src, Align Alignment, unsigned AddressSpace, | |
| TTI::TargetCostKind CostKind, TTI::OperandValueInfo OpInfo, | |
| const Instruction *I) const { | |
| assert((I == nullptr || I->getOpcode() == Opcode) && | |
| "Opcode should reflect passed instruction."); | |
| InstructionCost Cost = TTIImpl->getMemoryOpCost( | |
| Opcode, Src, Alignment, AddressSpace, CostKind, OpInfo, I); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getInterleavedMemoryOpCost( | |
| unsigned Opcode, Type *VecTy, unsigned Factor, ArrayRef<unsigned> Indices, | |
| Align Alignment, unsigned AddressSpace, TTI::TargetCostKind CostKind, | |
| bool UseMaskForCond, bool UseMaskForGaps) const { | |
| InstructionCost Cost = TTIImpl->getInterleavedMemoryOpCost( | |
| Opcode, VecTy, Factor, Indices, Alignment, AddressSpace, CostKind, | |
| UseMaskForCond, UseMaskForGaps); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getIntrinsicInstrCost(ICA, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getMemIntrinsicInstrCost( | |
| const MemIntrinsicCostAttributes &MICA, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getMemIntrinsicInstrCost(MICA, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getCallInstrCost(Function *F, Type *RetTy, | |
| ArrayRef<Type *> Tys, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = TTIImpl->getCallInstrCost(F, RetTy, Tys, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| unsigned TargetTransformInfo::getNumberOfParts(Type *Tp) const { | |
| return TTIImpl->getNumberOfParts(Tp); | |
| } | |
| InstructionCost TargetTransformInfo::getAddressComputationCost( | |
| Type *PtrTy, ScalarEvolution *SE, const SCEV *Ptr, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getAddressComputationCost(PtrTy, SE, Ptr, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getMemcpyCost(const Instruction *I) const { | |
| InstructionCost Cost = TTIImpl->getMemcpyCost(I); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| uint64_t TargetTransformInfo::getMaxMemIntrinsicInlineSizeThreshold() const { | |
| return TTIImpl->getMaxMemIntrinsicInlineSizeThreshold(); | |
| } | |
| InstructionCost TargetTransformInfo::getArithmeticReductionCost( | |
| unsigned Opcode, VectorType *Ty, std::optional<FastMathFlags> FMF, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getArithmeticReductionCost(Opcode, Ty, FMF, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getMinMaxReductionCost( | |
| Intrinsic::ID IID, VectorType *Ty, FastMathFlags FMF, | |
| TTI::TargetCostKind CostKind) const { | |
| InstructionCost Cost = | |
| TTIImpl->getMinMaxReductionCost(IID, Ty, FMF, CostKind); | |
| assert(Cost >= 0 && "TTI should not produce negative costs!"); | |
| return Cost; | |
| } | |
| InstructionCost TargetTransformInfo::getExtendedReductionCost( | |
| unsigned Opcode, bool IsUnsigned, Type *ResTy, VectorType *Ty, | |
| std::optional<FastMathFlags> FMF, TTI::TargetCostKind CostKind) const { | |
| return TTIImpl->getExtendedReductionCost(Opcode, IsUnsigned, ResTy, Ty, FMF, | |
| CostKind); | |
| } | |
| InstructionCost TargetTransformInfo::getMulAccReductionCost( | |
| bool IsUnsigned, unsigned RedOpcode, Type *ResTy, VectorType *Ty, | |
| TTI::TargetCostKind CostKind) const { | |
| return TTIImpl->getMulAccReductionCost(IsUnsigned, RedOpcode, ResTy, Ty, | |
| CostKind); | |
| } | |
| InstructionCost | |
| TargetTransformInfo::getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const { | |
| return TTIImpl->getCostOfKeepingLiveOverCall(Tys); | |
| } | |
| bool TargetTransformInfo::getTgtMemIntrinsic(IntrinsicInst *Inst, | |
| MemIntrinsicInfo &Info) const { | |
| return TTIImpl->getTgtMemIntrinsic(Inst, Info); | |
| } | |
| unsigned TargetTransformInfo::getAtomicMemIntrinsicMaxElementSize() const { | |
| return TTIImpl->getAtomicMemIntrinsicMaxElementSize(); | |
| } | |
| Value *TargetTransformInfo::getOrCreateResultFromMemIntrinsic( | |
| IntrinsicInst *Inst, Type *ExpectedType, bool CanCreate) const { | |
| return TTIImpl->getOrCreateResultFromMemIntrinsic(Inst, ExpectedType, | |
| CanCreate); | |
| } | |
| Type *TargetTransformInfo::getMemcpyLoopLoweringType( | |
| LLVMContext &Context, Value *Length, unsigned SrcAddrSpace, | |
| unsigned DestAddrSpace, Align SrcAlign, Align DestAlign, | |
| std::optional<uint32_t> AtomicElementSize) const { | |
| return TTIImpl->getMemcpyLoopLoweringType(Context, Length, SrcAddrSpace, | |
| DestAddrSpace, SrcAlign, DestAlign, | |
| AtomicElementSize); | |
| } | |
| void TargetTransformInfo::getMemcpyLoopResidualLoweringType( | |
| SmallVectorImpl<Type *> &OpsOut, LLVMContext &Context, | |
| unsigned RemainingBytes, unsigned SrcAddrSpace, unsigned DestAddrSpace, | |
| Align SrcAlign, Align DestAlign, | |
| std::optional<uint32_t> AtomicCpySize) const { | |
| TTIImpl->getMemcpyLoopResidualLoweringType( | |
| OpsOut, Context, RemainingBytes, SrcAddrSpace, DestAddrSpace, SrcAlign, | |
| DestAlign, AtomicCpySize); | |
| } | |
| bool TargetTransformInfo::areInlineCompatible(const Function *Caller, | |
| const Function *Callee) const { | |
| return TTIImpl->areInlineCompatible(Caller, Callee); | |
| } | |
| unsigned | |
| TargetTransformInfo::getInlineCallPenalty(const Function *F, | |
| const CallBase &Call, | |
| unsigned DefaultCallPenalty) const { | |
| return TTIImpl->getInlineCallPenalty(F, Call, DefaultCallPenalty); | |
| } | |
| bool TargetTransformInfo::shouldCopyAttributeWhenOutliningFrom( | |
| const Function *Caller, const Attribute &Attr) const { | |
| return TTIImpl->shouldCopyAttributeWhenOutliningFrom(Caller, Attr); | |
| } | |
| bool TargetTransformInfo::areTypesABICompatible(const Function *Caller, | |
| const Function *Callee, | |
| ArrayRef<Type *> Types) const { | |
| return TTIImpl->areTypesABICompatible(Caller, Callee, Types); | |
| } | |
| bool TargetTransformInfo::isIndexedLoadLegal(MemIndexedMode Mode, | |
| Type *Ty) const { | |
| return TTIImpl->isIndexedLoadLegal(Mode, Ty); | |
| } | |
| bool TargetTransformInfo::isIndexedStoreLegal(MemIndexedMode Mode, | |
| Type *Ty) const { | |
| return TTIImpl->isIndexedStoreLegal(Mode, Ty); | |
| } | |
| unsigned TargetTransformInfo::getLoadStoreVecRegBitWidth(unsigned AS) const { | |
| return TTIImpl->getLoadStoreVecRegBitWidth(AS); | |
| } | |
| bool TargetTransformInfo::isLegalToVectorizeLoad(LoadInst *LI) const { | |
| return TTIImpl->isLegalToVectorizeLoad(LI); | |
| } | |
| bool TargetTransformInfo::isLegalToVectorizeStore(StoreInst *SI) const { | |
| return TTIImpl->isLegalToVectorizeStore(SI); | |
| } | |
| bool TargetTransformInfo::isLegalToVectorizeLoadChain( | |
| unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const { | |
| return TTIImpl->isLegalToVectorizeLoadChain(ChainSizeInBytes, Alignment, | |
| AddrSpace); | |
| } | |
| bool TargetTransformInfo::isLegalToVectorizeStoreChain( | |
| unsigned ChainSizeInBytes, Align Alignment, unsigned AddrSpace) const { | |
| return TTIImpl->isLegalToVectorizeStoreChain(ChainSizeInBytes, Alignment, | |
| AddrSpace); | |
| } | |
| bool TargetTransformInfo::isLegalToVectorizeReduction( | |
| const RecurrenceDescriptor &RdxDesc, ElementCount VF) const { | |
| return TTIImpl->isLegalToVectorizeReduction(RdxDesc, VF); | |
| } | |
| bool TargetTransformInfo::isElementTypeLegalForScalableVector(Type *Ty) const { | |
| return TTIImpl->isElementTypeLegalForScalableVector(Ty); | |
| } | |
| unsigned TargetTransformInfo::getLoadVectorFactor(unsigned VF, | |
| unsigned LoadSize, | |
| unsigned ChainSizeInBytes, | |
| VectorType *VecTy) const { | |
| return TTIImpl->getLoadVectorFactor(VF, LoadSize, ChainSizeInBytes, VecTy); | |
| } | |
| unsigned TargetTransformInfo::getStoreVectorFactor(unsigned VF, | |
| unsigned StoreSize, | |
| unsigned ChainSizeInBytes, | |
| VectorType *VecTy) const { | |
| return TTIImpl->getStoreVectorFactor(VF, StoreSize, ChainSizeInBytes, VecTy); | |
| } | |
| bool TargetTransformInfo::preferFixedOverScalableIfEqualCost() const { | |
| return TTIImpl->preferFixedOverScalableIfEqualCost(); | |
| } | |
| bool TargetTransformInfo::preferInLoopReduction(RecurKind Kind, | |
| Type *Ty) const { | |
| return TTIImpl->preferInLoopReduction(Kind, Ty); | |
| } | |
| bool TargetTransformInfo::preferAlternateOpcodeVectorization() const { | |
| return TTIImpl->preferAlternateOpcodeVectorization(); | |
| } | |
| bool TargetTransformInfo::preferSLPInstCountCheck() const { | |
| return TTIImpl->preferSLPInstCountCheck(); | |
| } | |
| bool TargetTransformInfo::preferPredicatedReductionSelect() const { | |
| return TTIImpl->preferPredicatedReductionSelect(); | |
| } | |
| bool TargetTransformInfo::preferEpilogueVectorization( | |
| ElementCount Iters) const { | |
| return TTIImpl->preferEpilogueVectorization(Iters); | |
| } | |
| bool TargetTransformInfo::shouldConsiderVectorizationRegPressure() const { | |
| return TTIImpl->shouldConsiderVectorizationRegPressure(); | |
| } | |
| TargetTransformInfo::VPLegalization | |
| TargetTransformInfo::getVPLegalizationStrategy(const VPIntrinsic &VPI) const { | |
| return TTIImpl->getVPLegalizationStrategy(VPI); | |
| } | |
| bool TargetTransformInfo::hasArmWideBranch(bool Thumb) const { | |
| return TTIImpl->hasArmWideBranch(Thumb); | |
| } | |
| APInt TargetTransformInfo::getFeatureMask(const Function &F) const { | |
| return TTIImpl->getFeatureMask(F); | |
| } | |
| APInt TargetTransformInfo::getPriorityMask(const Function &F) const { | |
| return TTIImpl->getPriorityMask(F); | |
| } | |
| bool TargetTransformInfo::isMultiversionedFunction(const Function &F) const { | |
| return TTIImpl->isMultiversionedFunction(F); | |
| } | |
| unsigned TargetTransformInfo::getMaxNumArgs() const { | |
| return TTIImpl->getMaxNumArgs(); | |
| } | |
| bool TargetTransformInfo::shouldExpandReduction(const IntrinsicInst *II) const { | |
| return TTIImpl->shouldExpandReduction(II); | |
| } | |
| TargetTransformInfo::ReductionShuffle | |
| TargetTransformInfo::getPreferredExpandedReductionShuffle( | |
| const IntrinsicInst *II) const { | |
| return TTIImpl->getPreferredExpandedReductionShuffle(II); | |
| } | |
| unsigned TargetTransformInfo::getGISelRematGlobalCost() const { | |
| return TTIImpl->getGISelRematGlobalCost(); | |
| } | |
| unsigned TargetTransformInfo::getMinTripCountTailFoldingThreshold() const { | |
| return TTIImpl->getMinTripCountTailFoldingThreshold(); | |
| } | |
| bool TargetTransformInfo::supportsScalableVectors() const { | |
| return TTIImpl->supportsScalableVectors(); | |
| } | |
| bool TargetTransformInfo::enableScalableVectorization() const { | |
| return TTIImpl->enableScalableVectorization(); | |
| } | |
| bool TargetTransformInfo::hasActiveVectorLength() const { | |
| return TTIImpl->hasActiveVectorLength(); | |
| } | |
| bool TargetTransformInfo::isProfitableToSinkOperands( | |
| Instruction *I, SmallVectorImpl<Use *> &OpsToSink) const { | |
| return TTIImpl->isProfitableToSinkOperands(I, OpsToSink); | |
| } | |
| bool TargetTransformInfo::isVectorShiftByScalarCheap(Type *Ty) const { | |
| return TTIImpl->isVectorShiftByScalarCheap(Ty); | |
| } | |
| unsigned | |
| TargetTransformInfo::getNumBytesToPadGlobalArray(unsigned Size, | |
| Type *ArrayType) const { | |
| return TTIImpl->getNumBytesToPadGlobalArray(Size, ArrayType); | |
| } | |
| void TargetTransformInfo::collectKernelLaunchBounds( | |
| const Function &F, | |
| SmallVectorImpl<std::pair<StringRef, int64_t>> &LB) const { | |
| return TTIImpl->collectKernelLaunchBounds(F, LB); | |
| } | |
| bool TargetTransformInfo::allowVectorElementIndexingUsingGEP() const { | |
| return TTIImpl->allowVectorElementIndexingUsingGEP(); | |
| } | |
| bool TargetTransformInfo::isUniform(const Instruction *I, | |
| const SmallBitVector &UniformArgs) const { | |
| return TTIImpl->isUniform(I, UniformArgs); | |
| } | |
| TargetTransformInfoImplBase::~TargetTransformInfoImplBase() = default; | |
| TargetIRAnalysis::TargetIRAnalysis() : TTICallback(&getDefaultTTI) {} | |
| TargetIRAnalysis::TargetIRAnalysis( | |
| std::function<Result(const Function &)> TTICallback) | |
| : TTICallback(std::move(TTICallback)) {} | |
| TargetIRAnalysis::Result TargetIRAnalysis::run(const Function &F, | |
| FunctionAnalysisManager &) { | |
| assert(!F.isIntrinsic() && "Should not request TTI for intrinsics"); | |
| return TTICallback(F); | |
| } | |
| AnalysisKey TargetIRAnalysis::Key; | |
| TargetIRAnalysis::Result TargetIRAnalysis::getDefaultTTI(const Function &F) { | |
| return Result(F.getDataLayout()); | |
| } | |
| // Register the basic pass. | |
| INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti", | |
| "Target Transform Information", false, true) | |
| char TargetTransformInfoWrapperPass::ID = 0; | |
| void TargetTransformInfoWrapperPass::anchor() {} | |
| TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass() | |
| : ImmutablePass(ID) {} | |
| TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass( | |
| TargetIRAnalysis TIRA) | |
| : ImmutablePass(ID), TIRA(std::move(TIRA)) {} | |
| TargetTransformInfo &TargetTransformInfoWrapperPass::getTTI(const Function &F) { | |
| FunctionAnalysisManager DummyFAM; | |
| TTI = TIRA.run(F, DummyFAM); | |
| return *TTI; | |
| } | |
| ImmutablePass * | |
| llvm::createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA) { | |
| return new TargetTransformInfoWrapperPass(std::move(TIRA)); | |
| } |