summaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2015-01-31 03:43:40 +0000
committerChandler Carruth <chandlerc@gmail.com>2015-01-31 03:43:40 +0000
commita6a87b595d3434175ee87d96d1fe182357cf2611 (patch)
tree3f0103978cac66e4625f907355f211a5a7996208 /lib/Analysis
parent81674807cc3b3bf903733214eac8fdc997291267 (diff)
[PM] Change the core design of the TTI analysis to use a polymorphic
type erased interface and a single analysis pass rather than an extremely complex analysis group. The end result is that the TTI analysis can contain a type erased implementation that supports the polymorphic TTI interface. We can build one from a target-specific implementation or from a dummy one in the IR. I've also factored all of the code into "mix-in"-able base classes, including CRTP base classes to facilitate calling back up to the most specialized form when delegating horizontally across the surface. These aren't as clean as I would like and I'm planning to work on cleaning some of this up, but I wanted to start by putting into the right form. There are a number of reasons for this change, and this particular design. The first and foremost reason is that an analysis group is complete overkill, and the chaining delegation strategy was so opaque, confusing, and high overhead that TTI was suffering greatly for it. Several of the TTI functions had failed to be implemented in all places because of the chaining-based delegation making there be no checking of this. A few other functions were implemented with incorrect delegation. The message to me was very clear working on this -- the delegation and analysis group structure was too confusing to be useful here. The other reason of course is that this is *much* more natural fit for the new pass manager. This will lay the ground work for a type-erased per-function info object that can look up the correct subtarget and even cache it. Yet another benefit is that this will significantly simplify the interaction of the pass managers and the TargetMachine. See the future work below. The downside of this change is that it is very, very verbose. I'm going to work to improve that, but it is somewhat an implementation necessity in C++ to do type erasure. =/ I discussed this design really extensively with Eric and Hal prior to going down this path, and afterward showed them the result. No one was really thrilled with it, but there doesn't seem to be a substantially better alternative. Using a base class and virtual method dispatch would make the code much shorter, but as discussed in the update to the programmer's manual and elsewhere, a polymorphic interface feels like the more principled approach even if this is perhaps the least compelling example of it. ;] Ultimately, there is still a lot more to be done here, but this was the huge chunk that I couldn't really split things out of because this was the interface change to TTI. I've tried to minimize all the other parts of this. The follow up work should include at least: 1) Improving the TargetMachine interface by having it directly return a TTI object. Because we have a non-pass object with value semantics and an internal type erasure mechanism, we can narrow the interface of the TargetMachine to *just* do what we need: build and return a TTI object that we can then insert into the pass pipeline. 2) Make the TTI object be fully specialized for a particular function. This will include splitting off a minimal form of it which is sufficient for the inliner and the old pass manager. 3) Add a new pass manager analysis which produces TTI objects from the target machine for each function. This may actually be done as part of #2 in order to use the new analysis to implement #2. 4) Work on narrowing the API between TTI and the targets so that it is easier to understand and less verbose to type erase. 5) Work on narrowing the API between TTI and its clients so that it is easier to understand and less verbose to forward. 6) Try to improve the CRTP-based delegation. I feel like this code is just a bit messy and exacerbating the complexity of implementing the TTI in each target. Many thanks to Eric and Hal for their help here. I ended up blocked on this somewhat more abruptly than I expected, and so I appreciate getting it sorted out very quickly. Differential Revision: http://reviews.llvm.org/D7293 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@227669 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/Analysis.cpp2
-rw-r--r--lib/Analysis/CostModel.cpp3
-rw-r--r--lib/Analysis/FunctionTargetTransformInfo.cpp6
-rw-r--r--lib/Analysis/IPA/InlineCost.cpp6
-rw-r--r--lib/Analysis/TargetTransformInfo.cpp627
5 files changed, 117 insertions, 527 deletions
diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index e56ff612216..92858e72c69 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/lib/Analysis/Analysis.cpp
@@ -65,7 +65,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeRegionOnlyPrinterPass(Registry);
initializeScalarEvolutionPass(Registry);
initializeScalarEvolutionAliasAnalysisPass(Registry);
- initializeTargetTransformInfoAnalysisGroup(Registry);
+ initializeTargetTransformInfoWrapperPassPass(Registry);
initializeTypeBasedAliasAnalysisPass(Registry);
initializeScopedNoAliasAAPass(Registry);
}
diff --git a/lib/Analysis/CostModel.cpp b/lib/Analysis/CostModel.cpp
index 1b74f8c19c5..7b5dfa2c7c8 100644
--- a/lib/Analysis/CostModel.cpp
+++ b/lib/Analysis/CostModel.cpp
@@ -83,7 +83,8 @@ CostModelAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
bool
CostModelAnalysis::runOnFunction(Function &F) {
this->F = &F;
- TTI = getAnalysisIfAvailable<TargetTransformInfo>();
+ auto *TTIWP = getAnalysisIfAvailable<TargetTransformInfoWrapperPass>();
+ TTI = TTIWP ? &TTIWP->getTTI() : nullptr;
return false;
}
diff --git a/lib/Analysis/FunctionTargetTransformInfo.cpp b/lib/Analysis/FunctionTargetTransformInfo.cpp
index a686bec4e73..36f182098b3 100644
--- a/lib/Analysis/FunctionTargetTransformInfo.cpp
+++ b/lib/Analysis/FunctionTargetTransformInfo.cpp
@@ -21,7 +21,7 @@ using namespace llvm;
#define DEBUG_TYPE "function-tti"
static const char ftti_name[] = "Function TargetTransformInfo";
INITIALIZE_PASS_BEGIN(FunctionTargetTransformInfo, "function_tti", ftti_name, false, true)
-INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_END(FunctionTargetTransformInfo, "function_tti", ftti_name, false, true)
char FunctionTargetTransformInfo::ID = 0;
@@ -38,13 +38,13 @@ FunctionTargetTransformInfo::FunctionTargetTransformInfo()
void FunctionTargetTransformInfo::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
- AU.addRequired<TargetTransformInfo>();
+ AU.addRequired<TargetTransformInfoWrapperPass>();
}
void FunctionTargetTransformInfo::releaseMemory() {}
bool FunctionTargetTransformInfo::runOnFunction(Function &F) {
Fn = &F;
- TTI = &getAnalysis<TargetTransformInfo>();
+ TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI();
return false;
}
diff --git a/lib/Analysis/IPA/InlineCost.cpp b/lib/Analysis/IPA/InlineCost.cpp
index 58ac5d33409..bbae2533889 100644
--- a/lib/Analysis/IPA/InlineCost.cpp
+++ b/lib/Analysis/IPA/InlineCost.cpp
@@ -1232,7 +1232,7 @@ void CallAnalyzer::dump() {
INITIALIZE_PASS_BEGIN(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
true, true)
-INITIALIZE_AG_DEPENDENCY(TargetTransformInfo)
+INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
INITIALIZE_PASS_END(InlineCostAnalysis, "inline-cost", "Inline Cost Analysis",
true, true)
@@ -1246,12 +1246,12 @@ InlineCostAnalysis::~InlineCostAnalysis() {}
void InlineCostAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
AU.addRequired<AssumptionCacheTracker>();
- AU.addRequired<TargetTransformInfo>();
+ AU.addRequired<TargetTransformInfoWrapperPass>();
CallGraphSCCPass::getAnalysisUsage(AU);
}
bool InlineCostAnalysis::runOnSCC(CallGraphSCC &SCC) {
- TTI = &getAnalysis<TargetTransformInfo>();
+ TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI();
ACT = &getAnalysis<AssumptionCacheTracker>();
return false;
}
diff --git a/lib/Analysis/TargetTransformInfo.cpp b/lib/Analysis/TargetTransformInfo.cpp
index ebc56bb354b..cdbce0d78c1 100644
--- a/lib/Analysis/TargetTransformInfo.cpp
+++ b/lib/Analysis/TargetTransformInfo.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/Analysis/TargetTransformInfoImpl.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
@@ -20,669 +21,257 @@ using namespace llvm;
#define DEBUG_TYPE "tti"
-// Setup the analysis group to manage the TargetTransformInfo passes.
-INITIALIZE_ANALYSIS_GROUP(TargetTransformInfo, "Target Information", NoTTI)
-char TargetTransformInfo::ID = 0;
+TargetTransformInfo::~TargetTransformInfo() {}
-TargetTransformInfo::~TargetTransformInfo() {
-}
-
-void TargetTransformInfo::pushTTIStack(Pass *P) {
- TopTTI = this;
- PrevTTI = &P->getAnalysis<TargetTransformInfo>();
-
- // Walk up the chain and update the top TTI pointer.
- for (TargetTransformInfo *PTTI = PrevTTI; PTTI; PTTI = PTTI->PrevTTI)
- PTTI->TopTTI = this;
-}
+TargetTransformInfo::TargetTransformInfo(TargetTransformInfo &&Arg)
+ : TTIImpl(std::move(Arg.TTIImpl)) {}
-void TargetTransformInfo::getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<TargetTransformInfo>();
+TargetTransformInfo &TargetTransformInfo::operator=(TargetTransformInfo &&RHS) {
+ TTIImpl = std::move(RHS.TTIImpl);
+ return *this;
}
unsigned TargetTransformInfo::getOperationCost(unsigned Opcode, Type *Ty,
Type *OpTy) const {
- return PrevTTI->getOperationCost(Opcode, Ty, OpTy);
-}
-
-unsigned TargetTransformInfo::getGEPCost(
- const Value *Ptr, ArrayRef<const Value *> Operands) const {
- return PrevTTI->getGEPCost(Ptr, Operands);
+ return TTIImpl->getOperationCost(Opcode, Ty, OpTy);
}
unsigned TargetTransformInfo::getCallCost(FunctionType *FTy,
int NumArgs) const {
- return PrevTTI->getCallCost(FTy, NumArgs);
+ return TTIImpl->getCallCost(FTy, NumArgs);
}
-unsigned TargetTransformInfo::getCallCost(const Function *F,
- int NumArgs) const {
- return PrevTTI->getCallCost(F, NumArgs);
-}
-
-unsigned TargetTransformInfo::getCallCost(
- const Function *F, ArrayRef<const Value *> Arguments) const {
- return PrevTTI->getCallCost(F, Arguments);
-}
-
-unsigned TargetTransformInfo::getIntrinsicCost(
- Intrinsic::ID IID, Type *RetTy, ArrayRef<Type *> ParamTys) const {
- return PrevTTI->getIntrinsicCost(IID, RetTy, ParamTys);
+unsigned
+TargetTransformInfo::getCallCost(const Function *F,
+ ArrayRef<const Value *> Arguments) const {
+ return TTIImpl->getCallCost(F, Arguments);
}
-unsigned TargetTransformInfo::getIntrinsicCost(
- Intrinsic::ID IID, Type *RetTy, ArrayRef<const Value *> Arguments) const {
- return PrevTTI->getIntrinsicCost(IID, RetTy, Arguments);
+unsigned
+TargetTransformInfo::getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
+ ArrayRef<const Value *> Arguments) const {
+ return TTIImpl->getIntrinsicCost(IID, RetTy, Arguments);
}
unsigned TargetTransformInfo::getUserCost(const User *U) const {
- return PrevTTI->getUserCost(U);
+ return TTIImpl->getUserCost(U);
}
bool TargetTransformInfo::hasBranchDivergence() const {
- return PrevTTI->hasBranchDivergence();
+ return TTIImpl->hasBranchDivergence();
}
bool TargetTransformInfo::isLoweredToCall(const Function *F) const {
- return PrevTTI->isLoweredToCall(F);
+ return TTIImpl->isLoweredToCall(F);
}
-void
-TargetTransformInfo::getUnrollingPreferences(const Function *F, Loop *L,
- UnrollingPreferences &UP) const {
- PrevTTI->getUnrollingPreferences(F, L, UP);
+void TargetTransformInfo::getUnrollingPreferences(
+ const Function *F, Loop *L, UnrollingPreferences &UP) const {
+ return TTIImpl->getUnrollingPreferences(F, L, UP);
}
bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const {
- return PrevTTI->isLegalAddImmediate(Imm);
+ return TTIImpl->isLegalAddImmediate(Imm);
}
bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const {
- return PrevTTI->isLegalICmpImmediate(Imm);
+ return TTIImpl->isLegalICmpImmediate(Imm);
}
-bool TargetTransformInfo::isLegalMaskedLoad(Type *DataType,
- int Consecutive) const {
- return false;
+bool TargetTransformInfo::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
+ int64_t BaseOffset,
+ bool HasBaseReg,
+ int64_t Scale) const {
+ return TTIImpl->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
+ Scale);
}
bool TargetTransformInfo::isLegalMaskedStore(Type *DataType,
int Consecutive) const {
- return false;
+ return TTIImpl->isLegalMaskedStore(DataType, Consecutive);
}
-
-bool TargetTransformInfo::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
- int64_t BaseOffset,
- bool HasBaseReg,
- int64_t Scale) const {
- return PrevTTI->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg,
- Scale);
+bool TargetTransformInfo::isLegalMaskedLoad(Type *DataType,
+ int Consecutive) const {
+ return TTIImpl->isLegalMaskedLoad(DataType, Consecutive);
}
int TargetTransformInfo::getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
int64_t BaseOffset,
bool HasBaseReg,
int64_t Scale) const {
- return PrevTTI->getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg,
+ return TTIImpl->getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg,
Scale);
}
bool TargetTransformInfo::isTruncateFree(Type *Ty1, Type *Ty2) const {
- return PrevTTI->isTruncateFree(Ty1, Ty2);
+ return TTIImpl->isTruncateFree(Ty1, Ty2);
}
bool TargetTransformInfo::isTypeLegal(Type *Ty) const {
- return PrevTTI->isTypeLegal(Ty);
+ return TTIImpl->isTypeLegal(Ty);
}
unsigned TargetTransformInfo::getJumpBufAlignment() const {
- return PrevTTI->getJumpBufAlignment();
+ return TTIImpl->getJumpBufAlignment();
}
unsigned TargetTransformInfo::getJumpBufSize() const {
- return PrevTTI->getJumpBufSize();
+ return TTIImpl->getJumpBufSize();
}
bool TargetTransformInfo::shouldBuildLookupTables() const {
- return PrevTTI->shouldBuildLookupTables();
+ return TTIImpl->shouldBuildLookupTables();
}
TargetTransformInfo::PopcntSupportKind
TargetTransformInfo::getPopcntSupport(unsigned IntTyWidthInBit) const {
- return PrevTTI->getPopcntSupport(IntTyWidthInBit);
+ return TTIImpl->getPopcntSupport(IntTyWidthInBit);
}
bool TargetTransformInfo::haveFastSqrt(Type *Ty) const {
- return PrevTTI->haveFastSqrt(Ty);
+ return TTIImpl->haveFastSqrt(Ty);
}
unsigned TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty) const {
- return PrevTTI->getIntImmCost(Imm, Ty);
+ return TTIImpl->getIntImmCost(Imm, Ty);
}
-unsigned TargetTransformInfo::getIntImmCost(unsigned Opc, unsigned Idx,
+unsigned TargetTransformInfo::getIntImmCost(unsigned Opcode, unsigned Idx,
const APInt &Imm, Type *Ty) const {
- return PrevTTI->getIntImmCost(Opc, Idx, Imm, Ty);
+ return TTIImpl->getIntImmCost(Opcode, Idx, Imm, Ty);
}
unsigned TargetTransformInfo::getIntImmCost(Intrinsic::ID IID, unsigned Idx,
const APInt &Imm, Type *Ty) const {
- return PrevTTI->getIntImmCost(IID, Idx, Imm, Ty);
+ return TTIImpl->getIntImmCost(IID, Idx, Imm, Ty);
}
unsigned TargetTransformInfo::getNumberOfRegisters(bool Vector) const {
- return PrevTTI->getNumberOfRegisters(Vector);
+ return TTIImpl->getNumberOfRegisters(Vector);
}
unsigned TargetTransformInfo::getRegisterBitWidth(bool Vector) const {
- return PrevTTI->getRegisterBitWidth(Vector);
+ return TTIImpl->getRegisterBitWidth(Vector);
}
unsigned TargetTransformInfo::getMaxInterleaveFactor() const {
- return PrevTTI->getMaxInterleaveFactor();
+ return TTIImpl->getMaxInterleaveFactor();
}
unsigned TargetTransformInfo::getArithmeticInstrCost(
- unsigned Opcode, Type *Ty, OperandValueKind Op1Info,
- OperandValueKind Op2Info, OperandValueProperties Opd1PropInfo,
+ unsigned Opcode, Type *Ty, OperandValueKind Opd1Info,
+ OperandValueKind Opd2Info, OperandValueProperties Opd1PropInfo,
OperandValueProperties Opd2PropInfo) const {
- return PrevTTI->getArithmeticInstrCost(Opcode, Ty, Op1Info, Op2Info,
+ return TTIImpl->getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info,
Opd1PropInfo, Opd2PropInfo);
}
-unsigned TargetTransformInfo::getShuffleCost(ShuffleKind Kind, Type *Tp,
+unsigned TargetTransformInfo::getShuffleCost(ShuffleKind Kind, Type *Ty,
int Index, Type *SubTp) const {
- return PrevTTI->getShuffleCost(Kind, Tp, Index, SubTp);
+ return TTIImpl->getShuffleCost(Kind, Ty, Index, SubTp);
}
unsigned TargetTransformInfo::getCastInstrCost(unsigned Opcode, Type *Dst,
Type *Src) const {
- return PrevTTI->getCastInstrCost(Opcode, Dst, Src);
+ return TTIImpl->getCastInstrCost(Opcode, Dst, Src);
}
unsigned TargetTransformInfo::getCFInstrCost(unsigned Opcode) const {
- return PrevTTI->getCFInstrCost(Opcode);
+ return TTIImpl->getCFInstrCost(Opcode);
}
unsigned TargetTransformInfo::getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
Type *CondTy) const {
- return PrevTTI->getCmpSelInstrCost(Opcode, ValTy, CondTy);
+ return TTIImpl->getCmpSelInstrCost(Opcode, ValTy, CondTy);
}
unsigned TargetTransformInfo::getVectorInstrCost(unsigned Opcode, Type *Val,
unsigned Index) const {
- return PrevTTI->getVectorInstrCost(Opcode, Val, Index);
+ return TTIImpl->getVectorInstrCost(Opcode, Val, Index);
}
unsigned TargetTransformInfo::getMemoryOpCost(unsigned Opcode, Type *Src,
unsigned Alignment,
unsigned AddressSpace) const {
- return PrevTTI->getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
+ return TTIImpl->getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
}
-unsigned
+unsigned
TargetTransformInfo::getMaskedMemoryOpCost(unsigned Opcode, Type *Src,
- unsigned Alignment,
- unsigned AddressSpace) const {
- return PrevTTI->getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
+ unsigned Alignment,
+ unsigned AddressSpace) const {
+ return TTIImpl->getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace);
}
unsigned
-TargetTransformInfo::getIntrinsicInstrCost(Intrinsic::ID ID,
- Type *RetTy,
+TargetTransformInfo::getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
ArrayRef<Type *> Tys) const {
- return PrevTTI->getIntrinsicInstrCost(ID, RetTy, Tys);
+ return TTIImpl->getIntrinsicInstrCost(ID, RetTy, Tys);
}
unsigned TargetTransformInfo::getNumberOfParts(Type *Tp) const {
- return PrevTTI->getNumberOfParts(Tp);
+ return TTIImpl->getNumberOfParts(Tp);
}
unsigned TargetTransformInfo::getAddressComputationCost(Type *Tp,
bool IsComplex) const {
- return PrevTTI->getAddressComputationCost(Tp, IsComplex);
+ return TTIImpl->getAddressComputationCost(Tp, IsComplex);
}
unsigned TargetTransformInfo::getReductionCost(unsigned Opcode, Type *Ty,
- bool IsPairwise) const {
- return PrevTTI->getReductionCost(Opcode, Ty, IsPairwise);
+ bool IsPairwiseForm) const {
+ return TTIImpl->getReductionCost(Opcode, Ty, IsPairwiseForm);
+}
+
+unsigned
+TargetTransformInfo::getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const {
+ return TTIImpl->getCostOfKeepingLiveOverCall(Tys);
}
-unsigned TargetTransformInfo::getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys)
- const {
- return PrevTTI->getCostOfKeepingLiveOverCall(Tys);
+bool TargetTransformInfo::getTgtMemIntrinsic(IntrinsicInst *Inst,
+ MemIntrinsicInfo &Info) const {
+ return TTIImpl->getTgtMemIntrinsic(Inst, Info);
}
Value *TargetTransformInfo::getOrCreateResultFromMemIntrinsic(
IntrinsicInst *Inst, Type *ExpectedType) const {
- return PrevTTI->getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
+ return TTIImpl->getOrCreateResultFromMemIntrinsic(Inst, ExpectedType);
}
-bool TargetTransformInfo::getTgtMemIntrinsic(IntrinsicInst *Inst,
- MemIntrinsicInfo &Info) const {
- return PrevTTI->getTgtMemIntrinsic(Inst, Info);
-}
+TargetTransformInfo::Concept::~Concept() {}
namespace {
-
-struct NoTTI final : ImmutablePass, TargetTransformInfo {
- const DataLayout *DL;
-
- NoTTI() : ImmutablePass(ID), DL(nullptr) {
- initializeNoTTIPass(*PassRegistry::getPassRegistry());
- }
-
- void initializePass() override {
- // Note that this subclass is special, and must *not* call initializeTTI as
- // it does not chain.
- TopTTI = this;
- PrevTTI = nullptr;
- DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
- DL = DLP ? &DLP->getDataLayout() : nullptr;
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- // Note that this subclass is special, and must *not* call
- // TTI::getAnalysisUsage as it breaks the recursion.
- }
-
- /// Pass identification.
- static char ID;
-
- /// Provide necessary pointer adjustments for the two base classes.
- void *getAdjustedAnalysisPointer(const void *ID) override {
- if (ID == &TargetTransformInfo::ID)
- return (TargetTransformInfo*)this;
- return this;
- }
-
- unsigned getOperationCost(unsigned Opcode, Type *Ty,
- Type *OpTy) const override {
- switch (Opcode) {
- default:
- // By default, just classify everything as 'basic'.
- return TCC_Basic;
-
- case Instruction::GetElementPtr:
- llvm_unreachable("Use getGEPCost for GEP operations!");
-
- case Instruction::BitCast:
- assert(OpTy && "Cast instructions must provide the operand type");
- if (Ty == OpTy || (Ty->isPointerTy() && OpTy->isPointerTy()))
- // Identity and pointer-to-pointer casts are free.
- return TCC_Free;
-
- // Otherwise, the default basic cost is used.
- return TCC_Basic;
-
- case Instruction::IntToPtr: {
- if (!DL)
- return TCC_Basic;
-
- // An inttoptr cast is free so long as the input is a legal integer type
- // which doesn't contain values outside the range of a pointer.
- unsigned OpSize = OpTy->getScalarSizeInBits();
- if (DL->isLegalInteger(OpSize) &&
- OpSize <= DL->getPointerTypeSizeInBits(Ty))
- return TCC_Free;
-
- // Otherwise it's not a no-op.
- return TCC_Basic;
- }
- case Instruction::PtrToInt: {
- if (!DL)
- return TCC_Basic;
-
- // A ptrtoint cast is free so long as the result is large enough to store
- // the pointer, and a legal integer type.
- unsigned DestSize = Ty->getScalarSizeInBits();
- if (DL->isLegalInteger(DestSize) &&
- DestSize >= DL->getPointerTypeSizeInBits(OpTy))
- return TCC_Free;
-
- // Otherwise it's not a no-op.
- return TCC_Basic;
- }
- case Instruction::Trunc:
- // trunc to a native type is free (assuming the target has compare and
- // shift-right of the same width).
- if (DL && DL->isLegalInteger(DL->getTypeSizeInBits(Ty)))
- return TCC_Free;
-
- return TCC_Basic;
- }
- }
-
- unsigned getGEPCost(const Value *Ptr,
- ArrayRef<const Value *> Operands) const override {
- // In the basic model, we just assume that all-constant GEPs will be folded
- // into their uses via addressing modes.
- for (unsigned Idx = 0, Size = Operands.size(); Idx != Size; ++Idx)
- if (!isa<Constant>(Operands[Idx]))
- return TCC_Basic;
-
- return TCC_Free;
- }
-
- unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const override
- {
- assert(FTy && "FunctionType must be provided to this routine.");
-
- // The target-independent implementation just measures the size of the
- // function by approximating that each argument will take on average one
- // instruction to prepare.
-
- if (NumArgs < 0)
- // Set the argument number to the number of explicit arguments in the
- // function.
- NumArgs = FTy->getNumParams();
-
- return TCC_Basic * (NumArgs + 1);
- }
-
- unsigned getCallCost(const Function *F, int NumArgs = -1) const override
- {
- assert(F && "A concrete function must be provided to this routine.");
-
- if (NumArgs < 0)
- // Set the argument number to the number of explicit arguments in the
- // function.
- NumArgs = F->arg_size();
-
- if (Intrinsic::ID IID = (Intrinsic::ID)F->getIntrinsicID()) {
- FunctionType *FTy = F->getFunctionType();
- SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end());
- return TopTTI->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys);
- }
-
- if (!TopTTI->isLoweredToCall(F))
- return TCC_Basic; // Give a basic cost if it will be lowered directly.
-
- return TopTTI->getCallCost(F->getFunctionType(), NumArgs);
- }
-
- unsigned getCallCost(const Function *F,
- ArrayRef<const Value *> Arguments) const override {
- // Simply delegate to generic handling of the call.
- // FIXME: We should use instsimplify or something else to catch calls which
- // will constant fold with these arguments.
- return TopTTI->getCallCost(F, Arguments.size());
- }
-
- unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<Type *> ParamTys) const override {
- switch (IID) {
- default:
- // Intrinsics rarely (if ever) have normal argument setup constraints.
- // Model them as having a basic instruction cost.
- // FIXME: This is wrong for libc intrinsics.
- return TCC_Basic;
-
- case Intrinsic::annotation:
- case Intrinsic::assume:
- case Intrinsic::dbg_declare:
- case Intrinsic::dbg_value:
- case Intrinsic::invariant_start:
- case Intrinsic::invariant_end:
- case Intrinsic::lifetime_start:
- case Intrinsic::lifetime_end:
- case Intrinsic::objectsize:
- case Intrinsic::ptr_annotation:
- case Intrinsic::var_annotation:
- case Intrinsic::experimental_gc_result_int:
- case Intrinsic::experimental_gc_result_float:
- case Intrinsic::experimental_gc_result_ptr:
- case Intrinsic::experimental_gc_result:
- case Intrinsic::experimental_gc_relocate:
- // These intrinsics don't actually represent code after lowering.
- return TCC_Free;
- }
- }
-
- unsigned
- getIntrinsicCost(Intrinsic::ID IID, Type *RetTy,
- ArrayRef<const Value *> Arguments) const override {
- // Delegate to the generic intrinsic handling code. This mostly provides an
- // opportunity for targets to (for example) special case the cost of
- // certain intrinsics based on constants used as arguments.
- SmallVector<Type *, 8> ParamTys;
- ParamTys.reserve(Arguments.size());
- for (unsigned Idx = 0, Size = Arguments.size(); Idx != Size; ++Idx)
- ParamTys.push_back(Arguments[Idx]->getType());
- return TopTTI->getIntrinsicCost(IID, RetTy, ParamTys);
- }
-
- unsigned getUserCost(const User *U) const override {
- if (isa<PHINode>(U))
- return TCC_Free; // Model all PHI nodes as free.
-
- if (const GEPOperator *GEP = dyn_cast<GEPOperator>(U)) {
- SmallVector<const Value *, 4> Indices(GEP->idx_begin(), GEP->idx_end());
- return TopTTI->getGEPCost(GEP->getPointerOperand(), Indices);
- }
-
- if (ImmutableCallSite CS = U) {
- const Function *F = CS.getCalledFunction();
- if (!F) {
- // Just use the called value type.
- Type *FTy = CS.getCalledValue()->getType()->getPointerElementType();
- return TopTTI->getCallCost(cast<FunctionType>(FTy), CS.arg_size());
- }
-
- SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end());
- return TopTTI->getCallCost(F, Arguments);
- }
-
- if (const CastInst *CI = dyn_cast<CastInst>(U)) {
- // Result of a cmp instruction is often extended (to be used by other
- // cmp instructions, logical or return instructions). These are usually
- // nop on most sane targets.
- if (isa<CmpInst>(CI->getOperand(0)))
- return TCC_Free;
- }
-
- // Otherwise delegate to the fully generic implementations.
- return getOperationCost(Operator::getOpcode(U), U->getType(),
- U->getNumOperands() == 1 ?
- U->getOperand(0)->getType() : nullptr);
- }
-
- bool hasBranchDivergence() const override { return false; }
-
- bool isLoweredToCall(const Function *F) const override {
- // 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
- // can take place in the future.
-
- if (F->isIntrinsic())
- return false;
-
- if (F->hasLocalLinkage() || !F->hasName())
- return true;
-
- StringRef Name = F->getName();
-
- // These will all likely lower to a single selection DAG node.
- if (Name == "copysign" || Name == "copysignf" || Name == "copysignl" ||
- Name == "fabs" || Name == "fabsf" || Name == "fabsl" || Name == "sin" ||
- Name == "fmin" || Name == "fminf" || Name == "fminl" ||
- Name == "fmax" || Name == "fmaxf" || Name == "fmaxl" ||
- Name == "sinf" || Name == "sinl" || Name == "cos" || Name == "cosf" ||
- Name == "cosl" || Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl")
- return false;
-
- // These are all likely to be optimized into something smaller.
- if (Name == "pow" || Name == "powf" || Name == "powl" || Name == "exp2" ||
- Name == "exp2l" || Name == "exp2f" || Name == "floor" || Name ==
- "floorf" || Name == "ceil" || Name == "round" || Name == "ffs" ||
- Name == "ffsl" || Name == "abs" || Name == "labs" || Name == "llabs")
- return false;
-
- return true;
- }
-
- void getUnrollingPreferences(const Function *, Loop *,
- UnrollingPreferences &) const override {}
-
- bool isLegalAddImmediate(int64_t Imm) const override {
- return false;
- }
-
- bool isLegalICmpImmediate(int64_t Imm) const override {
- return false;
- }
-
- bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
- bool HasBaseReg, int64_t Scale) const override
- {
- // Guess that reg+reg addressing is allowed. This heuristic is taken from
- // the implementation of LSR.
- return !BaseGV && BaseOffset == 0 && Scale <= 1;
- }
-
- int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
- bool HasBaseReg, int64_t Scale) const override {
- // Guess that all legal addressing mode are free.
- if(isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale))
- return 0;
- return -1;
- }
-
- bool isTruncateFree(Type *Ty1, Type *Ty2) const override {
- return false;
- }
-
- bool isTypeLegal(Type *Ty) const override {
- return false;
- }
-
- unsigned getJumpBufAlignment() const override {
- return 0;
- }
-
- unsigned getJumpBufSize() const override {
- return 0;
- }
-
- bool shouldBuildLookupTables() const override {
- return true;
- }
-
- PopcntSupportKind
- getPopcntSupport(unsigned IntTyWidthInBit) const override {
- return PSK_Software;
- }
-
- bool haveFastSqrt(Type *Ty) const override {
- return false;
- }
-
- unsigned getIntImmCost(const APInt &Imm, Type *Ty) const override {
- return TCC_Basic;
- }
-
- unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm,
- Type *Ty) const override {
- return TCC_Free;
- }
-
- unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm,
- Type *Ty) const override {
- return TCC_Free;
- }
-
- unsigned getNumberOfRegisters(bool Vector) const override {
- return 8;
- }
-
- unsigned getRegisterBitWidth(bool Vector) const override {
- return 32;
- }
-
- unsigned getMaxInterleaveFactor() const override {
- return 1;
- }
-
- unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind,
- OperandValueKind, OperandValueProperties,
- OperandValueProperties) const override {
- return 1;
- }
-
- unsigned getShuffleCost(ShuffleKind Kind, Type *Ty,
- int Index = 0, Type *SubTp = nullptr) const override {
- return 1;
- }
-
- unsigned getCastInstrCost(unsigned Opcode, Type *Dst,
- Type *Src) const override {
- return 1;
- }
-
- unsigned getCFInstrCost(unsigned Opcode) const override {
- return 1;
- }
-
- unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy,
- Type *CondTy = nullptr) const override {
- return 1;
- }
-
- unsigned getVectorInstrCost(unsigned Opcode, Type *Val,
- unsigned Index = -1) const override {
- return 1;
- }
-
- unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) const override {
- return 1;
- }
-
- unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment,
- unsigned AddressSpace) const override {
- return 1;
- }
-
- unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy,
- ArrayRef<Type*> Tys) const override {
- return 1;
- }
-
- unsigned getNumberOfParts(Type *Tp) const override {
- return 0;
- }
-
- unsigned getAddressComputationCost(Type *Tp, bool) const override {
- return 0;
- }
-
- unsigned getReductionCost(unsigned, Type *, bool) const override {
- return 1;
- }
-
- unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const override {
- return 0;
- }
-
- bool getTgtMemIntrinsic(IntrinsicInst *Inst,
- MemIntrinsicInfo &Info) const override {
- return false;
- }
-
- Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst,
- Type *ExpectedType) const override {
- return nullptr;
- }
+/// \brief 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) {}
};
+}
+
+// Register the basic pass.
+INITIALIZE_PASS(TargetTransformInfoWrapperPass, "tti",
+ "Target Transform Information", false, true)
+char TargetTransformInfoWrapperPass::ID = 0;
-} // end anonymous namespace
+void TargetTransformInfoWrapperPass::anchor() {}
-INITIALIZE_AG_PASS(NoTTI, TargetTransformInfo, "notti",
- "No target information", true, true, true)
-char NoTTI::ID = 0;
+TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass()
+ : ImmutablePass(ID), TTI(NoTTIImpl(/*DataLayout*/ nullptr)) {
+ initializeTargetTransformInfoWrapperPassPass(
+ *PassRegistry::getPassRegistry());
+}
+
+TargetTransformInfoWrapperPass::TargetTransformInfoWrapperPass(
+ TargetTransformInfo TTI)
+ : ImmutablePass(ID), TTI(std::move(TTI)) {
+ initializeTargetTransformInfoWrapperPassPass(
+ *PassRegistry::getPassRegistry());
+}
-ImmutablePass *llvm::createNoTargetTransformInfoPass() {
- return new NoTTI();
+ImmutablePass *llvm::createNoTargetTransformInfoPass(const DataLayout *DL) {
+ return new TargetTransformInfoWrapperPass(NoTTIImpl(DL));
}