From 7bdf6b00e04c177f22133b5d4be10cb246cb1e76 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 5 Jan 2013 11:43:11 +0000 Subject: [PATCH] Convert the TargetTransformInfo from an immutable pass with dynamic interfaces which could be extracted from it, and must be provided on construction, to a chained analysis group. The end goal here is that TTI works much like AA -- there is a baseline "no-op" and target independent pass which is in the group, and each target can expose a target-specific pass in the group. These passes will naturally chain allowing each target-specific pass to delegate to the generic pass as needed. In particular, this will allow a much simpler interface for passes that would like to use TTI -- they can have a hard dependency on TTI and it will just be satisfied by the stub implementation when that is all that is available. This patch is a WIP however. In particular, the "stub" pass is actually the one and only pass, and everything there is implemented by delegating to the target-provided interfaces. As a consequence the tools still have to explicitly construct the pass. Switching targets to provide custom passes and sinking the stub behavior into the NoTTI pass is the next step. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171621 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/InitializePasses.h | 3 +- include/llvm/TargetTransformInfo.h | 331 +++++++++++++---------------- lib/IR/Core.cpp | 1 + lib/IR/TargetTransformInfo.cpp | 262 +++++++++++++++++++++-- lib/Target/Target.cpp | 1 - tools/llc/llc.cpp | 4 +- tools/opt/opt.cpp | 4 +- 7 files changed, 398 insertions(+), 208 deletions(-) diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index ee08fe0f797..9ee74dde1dd 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -250,7 +250,8 @@ void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeDataLayoutPass(PassRegistry&); -void initializeTargetTransformInfoPass(PassRegistry&); +void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); +void initializeNoTTIPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); diff --git a/include/llvm/TargetTransformInfo.h b/include/llvm/TargetTransformInfo.h index 197fdcbeef1..97d0304a38b 100644 --- a/include/llvm/TargetTransformInfo.h +++ b/include/llvm/TargetTransformInfo.h @@ -30,16 +30,34 @@ namespace llvm { -// ---------------------------------------------------------------------------// -// The classes below are inherited and implemented by target-specific classes -// in the codegen. -// ---------------------------------------------------------------------------// +class ScalarTargetTransformInfo; +class VectorTargetTransformInfo; + +/// TargetTransformInfo - This pass provides access to the codegen +/// interfaces that are needed for IR-level transformations. +class TargetTransformInfo { +protected: + /// \brief The TTI instance one level down the stack. + /// + /// This is used to implement the default behavior all of the methods which + /// is to delegate up through the stack of TTIs until one can answer the + /// query. + const TargetTransformInfo *PrevTTI; + + /// Every subclass must initialize the base with the previous TTI in the + /// stack, or 0 if there is no previous TTI in the stack. + TargetTransformInfo(const TargetTransformInfo *PrevTTI) : PrevTTI(PrevTTI) {} + + /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; -/// ScalarTargetTransformInfo - This interface is used by IR-level passes -/// that need target-dependent information for generic scalar transformations. -/// LSR, and LowerInvoke use this interface. -class ScalarTargetTransformInfo { public: + /// This class is intended to be subclassed by real implementations. + virtual ~TargetTransformInfo() = 0; + + /// \name Scalar Target Information + /// @{ + /// PopcntHwSupport - Hardware support for population count. Compared to the /// SW implementation, HW support is supposed to significantly boost the /// performance when the population is dense, and it may or may not degrade @@ -52,22 +70,18 @@ public: Slow }; - virtual ~ScalarTargetTransformInfo() {} - /// isLegalAddImmediate - Return true if the specified immediate is legal /// add immediate, that is the target has add instructions which can add /// a register with the immediate without having to materialize the /// immediate into a register. - virtual bool isLegalAddImmediate(int64_t) const { - return false; - } + virtual bool isLegalAddImmediate(int64_t Imm) const; + /// isLegalICmpImmediate - Return true if the specified immediate is legal /// icmp immediate, that is the target has icmp instructions which can compare /// a register against the immediate without having to materialize the /// immediate into a register. - virtual bool isLegalICmpImmediate(int64_t) const { - return false; - } + virtual bool isLegalICmpImmediate(int64_t Imm) const; + /// isLegalAddressingMode - Return true if the addressing mode represented by /// AM is legal for this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing @@ -75,53 +89,37 @@ public: /// TODO: Handle pre/postinc as well. virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const { - return false; - } + int64_t Scale) const; + /// isTruncateFree - Return true if it's free to truncate a value of /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in /// register EAX to i16 by referencing its sub-register AX. - virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const { - return false; - } + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const; + /// Is this type legal. - virtual bool isTypeLegal(Type *Ty) const { - return false; - } + virtual bool isTypeLegal(Type *Ty) const; + /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes - virtual unsigned getJumpBufAlignment() const { - return 0; - } + virtual unsigned getJumpBufAlignment() const; + /// getJumpBufSize - returns the target's jmp_buf size in bytes. - virtual unsigned getJumpBufSize() const { - return 0; - } + virtual unsigned getJumpBufSize() const; + /// shouldBuildLookupTables - Return true if switches should be turned into /// lookup tables for the target. - virtual bool shouldBuildLookupTables() const { - return true; - } + virtual bool shouldBuildLookupTables() const; + /// getPopcntHwSupport - Return hardware support for population count. - virtual PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const { - return None; - } + virtual PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const; + /// getIntImmCost - Return the expected cost of materializing the given /// integer immediate of the specified type. - virtual unsigned getIntImmCost(const APInt&, Type*) const { - // The default assumption is that the immediate is cheap. - return 1; - } -}; + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; -/// VectorTargetTransformInfo - This interface is used by the vectorizers -/// to estimate the profitability of vectorization for different instructions. -/// This interface provides the cost of different IR instructions. The cost -/// is unit-less and represents the estimated throughput of the instruction -/// (not the latency!) assuming that all branches are predicted, cache is hit, -/// etc. -class VectorTargetTransformInfo { -public: - virtual ~VectorTargetTransformInfo() {} + /// @} + + /// \name Vector Target Information + /// @{ enum ShuffleKind { Broadcast, // Broadcast element 0 to all other elements. @@ -133,96 +131,73 @@ public: /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. - virtual unsigned getNumberOfRegisters(bool Vector) const { - return 8; - } + virtual unsigned getNumberOfRegisters(bool Vector) const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const { - return 1; - } + virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const; /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. - virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, - int Index = 0, Type *SubTp = 0) const { - return 1; - } + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = 0) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const { - return 1; - } + Type *Src) const; /// \return The expected cost of control-flow related instrutctions such as /// Phi, Ret, Br. - virtual unsigned getCFInstrCost(unsigned Opcode) const { - return 1; - } + virtual unsigned getCFInstrCost(unsigned Opcode) const; /// \returns The expected cost of compare and select instructions. virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = 0) const { - return 1; - } + Type *CondTy = 0) const; /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index = -1) const { - return 1; - } + unsigned Index = -1) const; /// \return The cost of Load and Store instructions. virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, - unsigned AddressSpace) const { - return 1; - } + unsigned AddressSpace) const; /// \returns The cost of Intrinsic instructions. - virtual unsigned getIntrinsicInstrCost(Intrinsic::ID, - Type *RetTy, - ArrayRef Tys) const { - return 1; - } + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef Tys) const; /// \returns The number of pieces into which the provided type must be /// split during legalization. Zero is returned when the answer is unknown. - virtual unsigned getNumberOfParts(Type *Tp) const { - return 0; - } -}; + virtual unsigned getNumberOfParts(Type *Tp) const; + /// @} -/// TargetTransformInfo - This pass provides access to the codegen -/// interfaces that are needed for IR-level transformations. -class TargetTransformInfo : public ImmutablePass { -private: - const ScalarTargetTransformInfo *STTI; - const VectorTargetTransformInfo *VTTI; -public: - /// Default ctor. - /// - /// @note This has to exist, because this is a pass, but it should never be - /// used. - TargetTransformInfo(); - - TargetTransformInfo(const ScalarTargetTransformInfo* S, - const VectorTargetTransformInfo *V) - : ImmutablePass(ID), STTI(S), VTTI(V) { - initializeTargetTransformInfoPass(*PassRegistry::getPassRegistry()); - } + /// Analysis group identification. + static char ID; +}; - TargetTransformInfo(const TargetTransformInfo &T) : - ImmutablePass(ID), STTI(T.STTI), VTTI(T.VTTI) { } +/// \brief Create the base case instance of a pass in the TTI analysis group. +/// +/// This class provides the base case for the stack of TTI analyses. It doesn't +/// delegate to anything and uses the STTI and VTTI objects passed in to +/// satisfy the queries. +ImmutablePass *createNoTTIPass(const ScalarTargetTransformInfo *S, + const VectorTargetTransformInfo *V); - /// \name Scalar Target Information - /// @{ +// ---------------------------------------------------------------------------// +// The classes below are inherited and implemented by target-specific classes +// in the codegen. +// ---------------------------------------------------------------------------// + +/// ScalarTargetTransformInfo - This interface is used by IR-level passes +/// that need target-dependent information for generic scalar transformations. +/// LSR, and LowerInvoke use this interface. +class ScalarTargetTransformInfo { +public: /// PopcntHwSupport - Hardware support for population count. Compared to the /// SW implementation, HW support is supposed to significantly boost the /// performance when the population is dense, and it may or may not degrade @@ -235,77 +210,76 @@ public: Slow }; + virtual ~ScalarTargetTransformInfo() {} + /// isLegalAddImmediate - Return true if the specified immediate is legal /// add immediate, that is the target has add instructions which can add /// a register with the immediate without having to materialize the /// immediate into a register. - bool isLegalAddImmediate(int64_t Imm) const { - return STTI->isLegalAddImmediate(Imm); + virtual bool isLegalAddImmediate(int64_t) const { + return false; } - /// isLegalICmpImmediate - Return true if the specified immediate is legal /// icmp immediate, that is the target has icmp instructions which can compare /// a register against the immediate without having to materialize the /// immediate into a register. - bool isLegalICmpImmediate(int64_t Imm) const { - return STTI->isLegalICmpImmediate(Imm); + virtual bool isLegalICmpImmediate(int64_t) const { + return false; } - /// isLegalAddressingMode - Return true if the addressing mode represented by /// AM is legal for this target, for a load/store of the specified type. /// The type may be VoidTy, in which case only return true if the addressing /// mode is legal for a load/store of any legal type. /// TODO: Handle pre/postinc as well. - bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const { - return STTI->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, - Scale); + return false; } - /// isTruncateFree - Return true if it's free to truncate a value of /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in /// register EAX to i16 by referencing its sub-register AX. - bool isTruncateFree(Type *Ty1, Type *Ty2) const { - return STTI->isTruncateFree(Ty1, Ty2); + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const { + return false; } - /// Is this type legal. - bool isTypeLegal(Type *Ty) const { - return STTI->isTypeLegal(Ty); + virtual bool isTypeLegal(Type *Ty) const { + return false; } - /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes - unsigned getJumpBufAlignment() const { - return STTI->getJumpBufAlignment(); + virtual unsigned getJumpBufAlignment() const { + return 0; } - /// getJumpBufSize - returns the target's jmp_buf size in bytes. - unsigned getJumpBufSize() const { - return STTI->getJumpBufSize(); + virtual unsigned getJumpBufSize() const { + return 0; } - /// shouldBuildLookupTables - Return true if switches should be turned into /// lookup tables for the target. - bool shouldBuildLookupTables() const { - return STTI->shouldBuildLookupTables(); + virtual bool shouldBuildLookupTables() const { + return true; } - /// getPopcntHwSupport - Return hardware support for population count. - PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const { - return (PopcntHwSupport)STTI->getPopcntHwSupport(IntTyWidthInBit); + virtual PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const { + return None; } - /// getIntImmCost - Return the expected cost of materializing the given /// integer immediate of the specified type. - unsigned getIntImmCost(const APInt &Imm, Type *Ty) const { - return STTI->getIntImmCost(Imm, Ty); + virtual unsigned getIntImmCost(const APInt&, Type*) const { + // The default assumption is that the immediate is cheap. + return 1; } +}; - /// @} - - /// \name Vector Target Information - /// @{ +/// VectorTargetTransformInfo - This interface is used by the vectorizers +/// to estimate the profitability of vectorization for different instructions. +/// This interface provides the cost of different IR instructions. The cost +/// is unit-less and represents the estimated throughput of the instruction +/// (not the latency!) assuming that all branches are predicted, cache is hit, +/// etc. +class VectorTargetTransformInfo { +public: + virtual ~VectorTargetTransformInfo() {} enum ShuffleKind { Broadcast, // Broadcast element 0 to all other elements. @@ -317,88 +291,71 @@ public: /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. - unsigned getNumberOfRegisters(bool Vector) const { - return VTTI->getNumberOfRegisters(Vector); + virtual unsigned getNumberOfRegisters(bool Vector) const { + return 8; } /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const { - return VTTI->getArithmeticInstrCost(Opcode, Ty); + virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const { + return 1; } /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and /// extraction shuffle kinds. - unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, - int Index = 0, Type *SubTp = 0) const { - return VTTI->getShuffleCost((VectorTargetTransformInfo::ShuffleKind)Kind, - Tp, Index, SubTp); + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, + int Index = 0, Type *SubTp = 0) const { + return 1; } /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. - unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const { - return VTTI->getCastInstrCost(Opcode, Dst, Src); + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, + Type *Src) const { + return 1; } /// \return The expected cost of control-flow related instrutctions such as /// Phi, Ret, Br. - unsigned getCFInstrCost(unsigned Opcode) const { - return VTTI->getCFInstrCost(Opcode); + virtual unsigned getCFInstrCost(unsigned Opcode) const { + return 1; } /// \returns The expected cost of compare and select instructions. - unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = 0) const { - return VTTI->getCmpSelInstrCost(Opcode, ValTy, CondTy); + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = 0) const { + return 1; } /// \return The expected cost of vector Insert and Extract. /// Use -1 to indicate that there is no information on the index value. - unsigned getVectorInstrCost(unsigned Opcode, Type *Val, - unsigned Index = -1) const { - return VTTI->getVectorInstrCost(Opcode, Val, Index); + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const { + return 1; } /// \return The cost of Load and Store instructions. - unsigned getMemoryOpCost(unsigned Opcode, Type *Src, - unsigned Alignment, - unsigned AddressSpace) const { - return VTTI->getMemoryOpCost(Opcode, Src, Alignment, AddressSpace);; + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) const { + return 1; } /// \returns The cost of Intrinsic instructions. - unsigned getIntrinsicInstrCost(Intrinsic::ID ID, - Type *RetTy, - ArrayRef Tys) const { - return VTTI->getIntrinsicInstrCost(ID, RetTy, Tys); + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID, + Type *RetTy, + ArrayRef Tys) const { + return 1; } /// \returns The number of pieces into which the provided type must be /// split during legalization. Zero is returned when the answer is unknown. - unsigned getNumberOfParts(Type *Tp) const { - return VTTI->getNumberOfParts(Tp); - } - - /// @} - - /// \name Legacy sub-object getters - /// @{ - - const ScalarTargetTransformInfo* getScalarTargetTransformInfo() const { - return STTI; - } - const VectorTargetTransformInfo* getVectorTargetTransformInfo() const { - return VTTI; + virtual unsigned getNumberOfParts(Type *Tp) const { + return 0; } - - /// @} - - /// Pass identification, replacement for typeid. - static char ID; }; + } // End llvm namespace #endif diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 2024ac9b050..0b09a22d753 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -41,6 +41,7 @@ void llvm::initializeCore(PassRegistry &Registry) { initializePrintFunctionPassPass(Registry); initializeVerifierPass(Registry); initializePreVerifierPass(Registry); + initializeTargetTransformInfoAnalysisGroup(Registry); } void LLVMInitializeCore(LLVMPassRegistryRef R) { diff --git a/lib/IR/TargetTransformInfo.cpp b/lib/IR/TargetTransformInfo.cpp index 209e1dba8f2..8d5fb0d40bd 100644 --- a/lib/IR/TargetTransformInfo.cpp +++ b/lib/IR/TargetTransformInfo.cpp @@ -12,20 +12,252 @@ using namespace llvm; -/// Default ctor. -/// -/// @note This has to exist, because this is a pass, but it should never be -/// used. -TargetTransformInfo::TargetTransformInfo() : ImmutablePass(ID) { - /// You are seeing this error because your pass required the TTI - /// using a call to "getAnalysis()", and you did - /// not initialize a machine target which can provide the TTI. - /// You should use "getAnalysisIfAvailable()" instead. - report_fatal_error("Bad TargetTransformInfo ctor used. " - "Tool did not specify a TargetTransformInfo to use?"); -} - -INITIALIZE_PASS(TargetTransformInfo, "targettransforminfo", - "Target Transform Info", false, true) +// Setup the analysis group to manage the TargetTransformInfo passes. +INITIALIZE_ANALYSIS_GROUP(TargetTransformInfo, "Target Information", NoTTI) char TargetTransformInfo::ID = 0; +TargetTransformInfo::~TargetTransformInfo() { +} + +void TargetTransformInfo::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); +} + +bool TargetTransformInfo::isLegalAddImmediate(int64_t Imm) const { + return PrevTTI->isLegalAddImmediate(Imm); +} + +bool TargetTransformInfo::isLegalICmpImmediate(int64_t Imm) const { + return PrevTTI->isLegalICmpImmediate(Imm); +} + +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::isTruncateFree(Type *Ty1, Type *Ty2) const { + return PrevTTI->isTruncateFree(Ty1, Ty2); +} + +bool TargetTransformInfo::isTypeLegal(Type *Ty) const { + return PrevTTI->isTypeLegal(Ty); +} + +unsigned TargetTransformInfo::getJumpBufAlignment() const { + return PrevTTI->getJumpBufAlignment(); +} + +unsigned TargetTransformInfo::getJumpBufSize() const { + return PrevTTI->getJumpBufSize(); +} + +bool TargetTransformInfo::shouldBuildLookupTables() const { + return PrevTTI->shouldBuildLookupTables(); +} + +TargetTransformInfo::PopcntHwSupport +TargetTransformInfo::getPopcntHwSupport(unsigned IntTyWidthInBit) const { + return PrevTTI->getPopcntHwSupport(IntTyWidthInBit); +} + +unsigned TargetTransformInfo::getIntImmCost(const APInt &Imm, Type *Ty) const { + return PrevTTI->getIntImmCost(Imm, Ty); +} + +unsigned TargetTransformInfo::getNumberOfRegisters(bool Vector) const { + return PrevTTI->getNumberOfRegisters(Vector); +} + +unsigned TargetTransformInfo::getArithmeticInstrCost(unsigned Opcode, + Type *Ty) const { + return PrevTTI->getArithmeticInstrCost(Opcode, Ty); +} + +unsigned TargetTransformInfo::getShuffleCost(ShuffleKind Kind, Type *Tp, + int Index, Type *SubTp) const { + return PrevTTI->getShuffleCost(Kind, Tp, Index, SubTp); +} + +unsigned TargetTransformInfo::getCastInstrCost(unsigned Opcode, Type *Dst, + Type *Src) const { + return PrevTTI->getCastInstrCost(Opcode, Dst, Src); +} + +unsigned TargetTransformInfo::getCFInstrCost(unsigned Opcode) const { + return PrevTTI->getCFInstrCost(Opcode); +} + +unsigned TargetTransformInfo::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) const { + return PrevTTI->getCmpSelInstrCost(Opcode, ValTy, CondTy); +} + +unsigned TargetTransformInfo::getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) const { + return PrevTTI->getVectorInstrCost(Opcode, Val, Index); +} + +unsigned TargetTransformInfo::getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) const { + return PrevTTI->getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + ; +} + +unsigned +TargetTransformInfo::getIntrinsicInstrCost(Intrinsic::ID ID, + Type *RetTy, + ArrayRef Tys) const { + return PrevTTI->getIntrinsicInstrCost(ID, RetTy, Tys); +} + +unsigned TargetTransformInfo::getNumberOfParts(Type *Tp) const { + return PrevTTI->getNumberOfParts(Tp); +} + + +namespace { + +class NoTTI : public ImmutablePass, public TargetTransformInfo { + const ScalarTargetTransformInfo *STTI; + const VectorTargetTransformInfo *VTTI; + +public: + // FIXME: This constructor doesn't work which breaks the use of NoTTI on the + // commandline. This has to be fixed for NoTTI to be fully usable as an + // analysis pass. + NoTTI() : ImmutablePass(ID), TargetTransformInfo(0) { + llvm_unreachable("Unsupported code path!"); + } + + NoTTI(const ScalarTargetTransformInfo *S, const VectorTargetTransformInfo *V) + : ImmutablePass(ID), + TargetTransformInfo(0), // NoTTI is special and doesn't delegate here. + STTI(S), VTTI(V) { + initializeNoTTIPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &AU) const { + // 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. + virtual void *getAdjustedAnalysisPointer(const void *ID) { + if (ID == &TargetTransformInfo::ID) + return (TargetTransformInfo*)this; + return this; + } + + + // Delegate all predicates through the STTI or VTTI interface. + + bool isLegalAddImmediate(int64_t Imm) const { + return STTI->isLegalAddImmediate(Imm); + } + + bool isLegalICmpImmediate(int64_t Imm) const { + return STTI->isLegalICmpImmediate(Imm); + } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const { + return STTI->isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, + Scale); + } + + bool isTruncateFree(Type *Ty1, Type *Ty2) const { + return STTI->isTruncateFree(Ty1, Ty2); + } + + bool isTypeLegal(Type *Ty) const { + return STTI->isTypeLegal(Ty); + } + + unsigned getJumpBufAlignment() const { + return STTI->getJumpBufAlignment(); + } + + unsigned getJumpBufSize() const { + return STTI->getJumpBufSize(); + } + + bool shouldBuildLookupTables() const { + return STTI->shouldBuildLookupTables(); + } + + PopcntHwSupport getPopcntHwSupport(unsigned IntTyWidthInBit) const { + return (PopcntHwSupport)STTI->getPopcntHwSupport(IntTyWidthInBit); + } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) const { + return STTI->getIntImmCost(Imm, Ty); + } + + unsigned getNumberOfRegisters(bool Vector) const { + return VTTI->getNumberOfRegisters(Vector); + } + + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty) const { + return VTTI->getArithmeticInstrCost(Opcode, Ty); + } + + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, + int Index = 0, Type *SubTp = 0) const { + return VTTI->getShuffleCost((VectorTargetTransformInfo::ShuffleKind)Kind, + Tp, Index, SubTp); + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, + Type *Src) const { + return VTTI->getCastInstrCost(Opcode, Dst, Src); + } + + unsigned getCFInstrCost(unsigned Opcode) const { + return VTTI->getCFInstrCost(Opcode); + } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = 0) const { + return VTTI->getCmpSelInstrCost(Opcode, ValTy, CondTy); + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const { + return VTTI->getVectorInstrCost(Opcode, Val, Index); + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) const { + return VTTI->getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, + Type *RetTy, + ArrayRef Tys) const { + return VTTI->getIntrinsicInstrCost(ID, RetTy, Tys); + } + + unsigned getNumberOfParts(Type *Tp) const { + return VTTI->getNumberOfParts(Tp); + } +}; + +} // end anonymous namespace + +INITIALIZE_AG_PASS(NoTTI, TargetTransformInfo, "no-tti", + "No target information", true, true, true) +char NoTTI::ID = 0; + +ImmutablePass *llvm::createNoTTIPass(const ScalarTargetTransformInfo *S, + const VectorTargetTransformInfo *V) { + return new NoTTI(S, V); +} diff --git a/lib/Target/Target.cpp b/lib/Target/Target.cpp index 3a8a9c9b332..9a78ebc3fac 100644 --- a/lib/Target/Target.cpp +++ b/lib/Target/Target.cpp @@ -26,7 +26,6 @@ using namespace llvm; void llvm::initializeTarget(PassRegistry &Registry) { initializeDataLayoutPass(Registry); initializeTargetLibraryInfoPass(Registry); - initializeTargetTransformInfoPass(Registry); } void LLVMInitializeTarget(LLVMPassRegistryRef R) { diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp index f81495cc7ea..68876ea22a2 100644 --- a/tools/llc/llc.cpp +++ b/tools/llc/llc.cpp @@ -321,8 +321,8 @@ static int compileModule(char **argv, LLVMContext &Context) { PM.add(TLI); if (target.get()) { - PM.add(new TargetTransformInfo(target->getScalarTargetTransformInfo(), - target->getVectorTargetTransformInfo())); + PM.add(createNoTTIPass(target->getScalarTargetTransformInfo(), + target->getVectorTargetTransformInfo())); } // Add the target data from the target machine, if it exists, or the module. diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 9c9e3940434..c2987f19edd 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -658,8 +658,8 @@ int main(int argc, char **argv) { std::auto_ptr TM(Machine); if (TM.get()) { - Passes.add(new TargetTransformInfo(TM->getScalarTargetTransformInfo(), - TM->getVectorTargetTransformInfo())); + Passes.add(createNoTTIPass(TM->getScalarTargetTransformInfo(), + TM->getVectorTargetTransformInfo())); } OwningPtr FPasses; -- 2.34.1