diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-05-27 18:44:32 +0000 |
commit | 5a5ac124e1efaf208671f01c46edb15f29ed2a0b (patch) | |
tree | a6140557876943cdd800ee997c9317283394b22c /include/llvm/Analysis | |
parent | f03b5bed27d0d2eafd68562ce14f8b5e3f1f0801 (diff) |
Vendor import of llvm trunk r238337:vendor/llvm/llvm-trunk-r238337
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=283625
svn path=/vendor/llvm/llvm-trunk-r238337/; revision=283626; tag=vendor/llvm/llvm-trunk-r238337
Diffstat (limited to 'include/llvm/Analysis')
42 files changed, 3684 insertions, 743 deletions
diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 763f37298811..ac9d21c590a4 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -68,7 +68,7 @@ protected: /// typically called by the run* methods of these subclasses. This may be /// called multiple times. /// - void InitializeAliasAnalysis(Pass *P); + void InitializeAliasAnalysis(Pass *P, const DataLayout *DL); /// getAnalysisUsage - All alias analysis implementations should invoke this /// directly (using AliasAnalysis::getAnalysisUsage(AU)). @@ -84,11 +84,6 @@ public: /// know the sizes of the potential memory references. static uint64_t const UnknownSize = ~UINT64_C(0); - /// getDataLayout - Return a pointer to the current DataLayout object, or - /// null if no DataLayout object is available. - /// - const DataLayout *getDataLayout() const { return DL; } - /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo /// object, or null if no TargetLibraryInfo object is available. /// @@ -139,6 +134,10 @@ public: Copy.AATags = AAMDNodes(); return Copy; } + + bool operator==(const AliasAnalysis::Location &Other) const { + return Ptr == Other.Ptr && Size == Other.Size && AATags == Other.AATags; + } }; /// getLocation - Fill in Loc with information about the memory reference by @@ -150,6 +149,19 @@ public: Location getLocation(const AtomicRMWInst *RMWI); static Location getLocationForSource(const MemTransferInst *MTI); static Location getLocationForDest(const MemIntrinsic *MI); + Location getLocation(const Instruction *Inst) { + if (auto *I = dyn_cast<LoadInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<StoreInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<VAArgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicRMWInst>(Inst)) + return getLocation(I); + llvm_unreachable("unsupported memory instruction"); + } /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers @@ -357,6 +369,24 @@ public: return (MRB & ModRef) && (MRB & ArgumentPointees); } + /// getModRefInfo - Return information about whether or not an + /// instruction may read or write memory (without regard to a + /// specific location) + ModRefResult getModRefInfo(const Instruction *I) { + if (auto CS = ImmutableCallSite(I)) { + auto MRB = getModRefBehavior(CS); + if (MRB & ModRef) + return ModRef; + else if (MRB & Ref) + return Ref; + else if (MRB & Mod) + return Mod; + return NoModRef; + } + + return getModRefInfo(I, Location()); + } + /// getModRefInfo - Return information about whether or not an instruction may /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. @@ -477,6 +507,10 @@ public: ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ return getModRefInfo(I, Location(P, Size)); } + /// getModRefInfo - Return information about whether a call and an instruction + /// may refer to the same memory locations. + ModRefResult getModRefInfo(Instruction *I, + ImmutableCallSite Call); /// getModRefInfo - Return information about whether two call sites may refer /// to the same set of memory locations. See @@ -585,9 +619,7 @@ struct DenseMapInfo<AliasAnalysis::Location> { } static bool isEqual(const AliasAnalysis::Location &LHS, const AliasAnalysis::Location &RHS) { - return LHS.Ptr == RHS.Ptr && - LHS.Size == RHS.Size && - LHS.AATags == RHS.AATags; + return LHS == RHS; } }; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index 036d58dfa810..18f95b401e6a 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -192,11 +192,6 @@ public: } bool operator!=(const iterator& x) const { return !operator==(x); } - const iterator &operator=(const iterator &I) { - CurNode = I.CurNode; - return *this; - } - value_type &operator*() const { assert(CurNode && "Dereferencing AliasSet.end()!"); return *CurNode; @@ -226,8 +221,8 @@ private: AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { } - AliasSet(const AliasSet &AS) LLVM_DELETED_FUNCTION; - void operator=(const AliasSet &AS) LLVM_DELETED_FUNCTION; + AliasSet(const AliasSet &AS) = delete; + void operator=(const AliasSet &AS) = delete; PointerRec *getSomePointer() const { return PtrList; @@ -273,7 +268,7 @@ public: /// bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; - bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; + bool aliasesUnknownInst(const Instruction *Inst, AliasAnalysis &AA) const; }; inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { @@ -363,7 +358,7 @@ public: /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. - AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, + AliasSet *getAliasSetForPointerIfExists(const Value *P, uint64_t Size, const AAMDNodes &AAInfo) { return findAliasSetForPointer(P, Size, AAInfo); } @@ -371,11 +366,12 @@ public: /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; + bool containsPointer(const Value *P, uint64_t Size, + const AAMDNodes &AAInfo) const; /// Return true if the specified instruction "may" (or must) alias one of the /// members in any of the sets. - bool containsUnknown(Instruction *I) const; + bool containsUnknown(const Instruction *I) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index b129e6796328..1f00b691b305 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -27,6 +27,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + /// \brief A cache of @llvm.assume calls within a function. /// /// This cache provides fast lookup of assumptions within a function by caching @@ -88,6 +93,42 @@ public: } }; +/// \brief A function analysis which provides an \c AssumptionCache. +/// +/// This analysis is intended for use with the new pass manager and will vend +/// assumption caches for a given function. +class AssumptionAnalysis { + static char PassID; + +public: + typedef AssumptionCache Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "AssumptionAnalysis"; } + + AssumptionAnalysis() {} + AssumptionAnalysis(const AssumptionAnalysis &Arg) {} + AssumptionAnalysis(AssumptionAnalysis &&Arg) {} + AssumptionAnalysis &operator=(const AssumptionAnalysis &RHS) { return *this; } + AssumptionAnalysis &operator=(AssumptionAnalysis &&RHS) { return *this; } + + AssumptionCache run(Function &F) { return AssumptionCache(F); } +}; + +/// \brief Printer pass for the \c AssumptionAnalysis results. +class AssumptionPrinterPass { + raw_ostream &OS; + +public: + explicit AssumptionPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "AssumptionPrinterPass"; } +}; + /// \brief An immutable pass that tracks lazily created \c AssumptionCache /// objects. /// @@ -124,7 +165,7 @@ public: AssumptionCache &getAssumptionCache(Function &F); AssumptionCacheTracker(); - ~AssumptionCacheTracker(); + ~AssumptionCacheTracker() override; void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index 3289a2823c0c..f27c32df9283 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -34,7 +34,7 @@ public: BlockFrequencyInfo(); - ~BlockFrequencyInfo(); + ~BlockFrequencyInfo() override; void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 57b515420925..9acc863a7382 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -718,9 +718,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// /// It has some known flaws. /// -/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting -/// BlockFrequency's 64-bit integer precision. -/// /// - The model of irreducible control flow is a rough approximation. /// /// Modelling irreducible control flow exactly involves setting up and diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 0d4fe932481b..6a406cd24402 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -263,8 +263,7 @@ private: template <typename CGSCCPassT> ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT> createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) { - return std::move( - ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass))); + return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass)); } /// \brief A CGSCC analysis which acts as a proxy for a function analysis @@ -484,7 +483,7 @@ private: template <typename FunctionPassT> CGSCCToFunctionPassAdaptor<FunctionPassT> createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { - return std::move(CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass))); + return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass)); } } diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 76d9073799f8..14b88220202a 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -273,8 +273,8 @@ private: /// CalledFunctions array of this or other CallGraphNodes. unsigned NumReferences; - CallGraphNode(const CallGraphNode &) LLVM_DELETED_FUNCTION; - void operator=(const CallGraphNode &) LLVM_DELETED_FUNCTION; + CallGraphNode(const CallGraphNode &) = delete; + void operator=(const CallGraphNode &) = delete; void DropRef() { --NumReferences; } void AddRef() { ++NumReferences; } @@ -318,7 +318,7 @@ public: static char ID; // Class identification, replacement for typeinfo CallGraphWrapperPass(); - virtual ~CallGraphWrapperPass(); + ~CallGraphWrapperPass() override; /// \brief The internal \c CallGraph around which the rest of this interface /// is wrapped. diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index 09d45ca2b486..541a2109af6c 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -36,16 +36,15 @@ namespace llvm { /// Note that this fails if not all of the operands are constant. Otherwise, /// this function can only fail when attempting to fold instructions like loads /// and stores, which have no constant expression form. -Constant *ConstantFoldInstruction(Instruction *I, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr); + Constant *ConstantFoldInstruction(Instruction *I, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldConstantExpression - Attempt to fold the constant expression /// using the specified DataLayout. If successful, the constant result is /// result is returned, if not, null is returned. -Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI =nullptr); + Constant * + ConstantFoldConstantExpression(const ConstantExpr *CE, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, @@ -53,19 +52,19 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE, /// fold instructions like loads and stores, which have no constant expression /// form. /// -Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, - ArrayRef<Constant *> Ops, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr); + Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy, + ArrayRef<Constant *> Ops, + const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare /// instruction (icmp/fcmp) with the specified operands. If it fails, it /// returns a constant expression of the specified operands. /// -Constant *ConstantFoldCompareInstOperands(unsigned Predicate, - Constant *LHS, Constant *RHS, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI=nullptr); + Constant * + ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS, + Constant *RHS, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr); /// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue /// instruction with the specified operands and indices. The constant result is @@ -76,8 +75,7 @@ Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val, /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// produce if it is constant and determinable. If this is not determinable, /// return null. -Constant *ConstantFoldLoadFromConstPtr(Constant *C, - const DataLayout *TD = nullptr); +Constant *ConstantFoldLoadFromConstPtr(Constant *C, const DataLayout &DL); /// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a /// getelementptr constantexpr, return the constant value being addressed by the diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h deleted file mode 100644 index d3d0a44bd6d4..000000000000 --- a/include/llvm/Analysis/ConstantsScanner.h +++ /dev/null @@ -1,93 +0,0 @@ -//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This class implements an iterator to walk through the constants referenced by -// a method. This is used by the Bitcode & Assembly writers to build constant -// pools. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H -#define LLVM_ANALYSIS_CONSTANTSSCANNER_H - -#include "llvm/IR/InstIterator.h" - -namespace llvm { - -class Constant; - -class constant_iterator : public std::iterator<std::forward_iterator_tag, - const Constant, ptrdiff_t> { - const_inst_iterator InstI; // Method instruction iterator - unsigned OpIdx; // Operand index - - typedef constant_iterator _Self; - - inline bool isAtConstant() const { - assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() && - "isAtConstant called with invalid arguments!"); - return isa<Constant>(InstI->getOperand(OpIdx)); - } - -public: - inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) { - // Advance to first constant... if we are not already at constant or end - if (InstI != inst_end(F) && // InstI is valid? - (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant? - operator++(); - } - - inline constant_iterator(const Function *F, bool) // end ctor - : InstI(inst_end(F)), OpIdx(0) { - } - - inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx && - InstI == x.InstI; } - inline bool operator!=(const _Self& x) const { return !operator==(x); } - - inline pointer operator*() const { - assert(isAtConstant() && "Dereferenced an iterator at the end!"); - return cast<Constant>(InstI->getOperand(OpIdx)); - } - inline pointer operator->() const { return operator*(); } - - inline _Self& operator++() { // Preincrement implementation - ++OpIdx; - do { - unsigned NumOperands = InstI->getNumOperands(); - while (OpIdx < NumOperands && !isAtConstant()) { - ++OpIdx; - } - - if (OpIdx < NumOperands) return *this; // Found a constant! - ++InstI; - OpIdx = 0; - } while (!InstI.atEnd()); - - return *this; // At the end of the method - } - - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; - } - - inline bool atEnd() const { return InstI.atEnd(); } -}; - -inline constant_iterator constant_begin(const Function *F) { - return constant_iterator(F); -} - -inline constant_iterator constant_end(const Function *F) { - return constant_iterator(F, true); -} - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 1041e3f0a4a9..0b3b2ea42813 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -217,13 +217,9 @@ namespace llvm { /// input dependences are unordered. class FullDependence : public Dependence { public: - FullDependence(Instruction *Src, - Instruction *Dst, - bool LoopIndependent, + FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, unsigned Levels); - ~FullDependence() { - delete[] DV; - } + ~FullDependence() override { delete[] DV; } /// isLoopIndependent - Returns true if this is a loop-independent /// dependence. @@ -266,6 +262,7 @@ namespace llvm { /// if no subscript in the source or destination mention the induction /// variable associated with the loop at this level. bool isScalar(unsigned Level) const override; + private: unsigned short Levels; bool LoopIndependent; @@ -278,8 +275,8 @@ namespace llvm { /// DependenceAnalysis - This class is the main dependence-analysis driver. /// class DependenceAnalysis : public FunctionPass { - void operator=(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; - DependenceAnalysis(const DependenceAnalysis &) LLVM_DELETED_FUNCTION; + void operator=(const DependenceAnalysis &) = delete; + DependenceAnalysis(const DependenceAnalysis &) = delete; public: /// depends - Tests for a dependence between the Src and Dst instructions. /// Returns NULL if no dependence; otherwise, returns a Dependence (or a diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 735bfb83671d..629ae3809045 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -19,11 +19,12 @@ #define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/GenericDomTree.h" namespace llvm { -namespace { template <class BlockT> class DFCalculateWorkObject { public: @@ -37,7 +38,6 @@ public: const DomTreeNodeT *Node; const DomTreeNodeT *parentNode; }; -} template <class BlockT> void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) { diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h deleted file mode 100644 index fce5a1a92bd9..000000000000 --- a/include/llvm/Analysis/FunctionTargetTransformInfo.h +++ /dev/null @@ -1,49 +0,0 @@ -//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass wraps a TargetTransformInfo in a FunctionPass so that it can -// forward along the current Function so that we can make target specific -// decisions based on the particular subtarget specified for each Function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H -#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H - -#include "TargetTransformInfo.h" -#include "llvm/Pass.h" - -namespace llvm { -class FunctionTargetTransformInfo final : public FunctionPass { -private: - const Function *Fn; - const TargetTransformInfo *TTI; - - FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) - LLVM_DELETED_FUNCTION; - void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; - -public: - static char ID; - FunctionTargetTransformInfo(); - - // Implementation boilerplate. - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnFunction(Function &F) override; - - // Shimmed functions from TargetTransformInfo. - void - getUnrollingPreferences(Loop *L, - TargetTransformInfo::UnrollingPreferences &UP) const { - TTI->getUnrollingPreferences(Fn, L, UP); - } -}; -} -#endif diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index d1f037021773..ae9c1f5bd9ac 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -122,7 +122,6 @@ class IVUsers : public LoopPass { LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - const DataLayout *DL; SmallPtrSet<Instruction*,16> Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index a064cfc897b0..79ed74d82411 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -23,7 +23,7 @@ class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; -class TargetTransformInfo; +class TargetTransformInfoWrapperPass; namespace InlineConstants { // Various magic constants used to adjust heuristics. @@ -77,7 +77,7 @@ public: } /// \brief Test whether the inline cost is low enough for inlining. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return Cost < Threshold; } @@ -100,14 +100,14 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { - const TargetTransformInfo *TTI; + TargetTransformInfoWrapperPass *TTIWP; AssumptionCacheTracker *ACT; public: static char ID; InlineCostAnalysis(); - ~InlineCostAnalysis(); + ~InlineCostAnalysis() override; // Pass interface implementation. void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index b88e0899f19a..706bd8000d3a 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -49,7 +49,7 @@ namespace llvm { /// SimplifyAddInst - Given operands for an Add, see if we can /// fold the result. If not, this returns null. Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -58,7 +58,7 @@ namespace llvm { /// SimplifySubInst - Given operands for a Sub, see if we can /// fold the result. If not, this returns null. Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -67,7 +67,7 @@ namespace llvm { /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -76,7 +76,7 @@ namespace llvm { /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -85,7 +85,7 @@ namespace llvm { /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -93,7 +93,7 @@ namespace llvm { /// SimplifyMulInst - Given operands for a Mul, see if we can /// fold the result. If not, this returns null. - Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -101,8 +101,7 @@ namespace llvm { /// SimplifySDivInst - Given operands for an SDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifySDivInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -110,8 +109,7 @@ namespace llvm { /// SimplifyUDivInst - Given operands for a UDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyUDivInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -119,8 +117,8 @@ namespace llvm { /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFDivInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyFDivInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -128,8 +126,7 @@ namespace llvm { /// SimplifySRemInst - Given operands for an SRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifySRemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -137,8 +134,7 @@ namespace llvm { /// SimplifyURemInst - Given operands for a URem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyURemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -146,8 +142,8 @@ namespace llvm { /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. - Value *SimplifyFRemInst(Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + Value *SimplifyFRemInst(Value *LHS, Value *RHS, FastMathFlags FMF, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -156,7 +152,7 @@ namespace llvm { /// SimplifyShlInst - Given operands for a Shl, see if we can /// fold the result. If not, this returns null. Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -165,7 +161,7 @@ namespace llvm { /// SimplifyLShrInst - Given operands for a LShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -174,7 +170,7 @@ namespace llvm { /// SimplifyAShrInst - Given operands for a AShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -182,7 +178,7 @@ namespace llvm { /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. - Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -190,7 +186,7 @@ namespace llvm { /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. - Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -198,7 +194,7 @@ namespace llvm { /// SimplifyXorInst - Given operands for a Xor, see if we can /// fold the result. If not, this returns null. - Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, + Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -207,7 +203,7 @@ namespace llvm { /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -216,7 +212,7 @@ namespace llvm { /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -225,7 +221,7 @@ namespace llvm { /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -233,7 +229,7 @@ namespace llvm { /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. - Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout *TD = nullptr, + Value *SimplifyGEPInst(ArrayRef<Value *> Ops, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -242,8 +238,7 @@ namespace llvm { /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we /// can fold the result. If not, this returns null. Value *SimplifyInsertValueInst(Value *Agg, Value *Val, - ArrayRef<unsigned> Idxs, - const DataLayout *TD = nullptr, + ArrayRef<unsigned> Idxs, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -251,7 +246,7 @@ namespace llvm { /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. - Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, + Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -263,7 +258,7 @@ namespace llvm { /// SimplifyCmpInst - Given operands for a CmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -272,18 +267,28 @@ namespace llvm { /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, - const DataLayout *TD = nullptr, + const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr); + /// SimplifyFPBinOp - Given operands for a BinaryOperator, see if we can + /// fold the result. If not, this returns null. + /// In contrast to SimplifyBinOp, try to use FastMathFlag when folding the + /// result. In case we don't need FastMathFlags, simply fall to SimplifyBinOp. + Value *SimplifyFPBinOp(unsigned Opcode, Value *LHS, Value *RHS, + const FastMathFlags &FMF, const DataLayout &DL, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. /// /// If this call could not be simplified returns null. Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, - User::op_iterator ArgEnd, const DataLayout *TD = nullptr, + User::op_iterator ArgEnd, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -293,8 +298,7 @@ namespace llvm { /// result. /// /// If this call could not be simplified returns null. - Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, - const DataLayout *TD = nullptr, + Value *SimplifyCall(Value *V, ArrayRef<Value *> Args, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, @@ -302,7 +306,7 @@ namespace llvm { /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. - Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, + Value *SimplifyInstruction(Instruction *I, const DataLayout &DL, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); @@ -316,7 +320,6 @@ namespace llvm { /// /// The function returns true if any simplifications were performed. bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); @@ -328,7 +331,6 @@ namespace llvm { /// of the users impacted. It returns true if any simplifications were /// performed. bool recursivelySimplifyInstruction(Instruction *I, - const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr); diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 3b51d44099fa..655ce2dab413 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -78,7 +78,7 @@ inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { // inline void addNodeToInterval(Interval *Int, Interval *I) { // Add all of the nodes in I as new nodes in Int. - copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); + Int->Nodes.insert(Int->Nodes.end(), I->Nodes.begin(), I->Nodes.end()); } @@ -94,7 +94,6 @@ class IntervalIterator { bool IOwnMem; // If True, delete intervals when done with them // See file header for conditions of use public: - typedef IntervalIterator<NodeTy, OrigContainer_t> _Self; typedef std::forward_iterator_tag iterator_category; IntervalIterator() {} // End iterator, empty stack @@ -105,6 +104,12 @@ public: } } + IntervalIterator(IntervalIterator &&x) + : IntStack(std::move(x.IntStack)), Visited(std::move(x.Visited)), + OrigContainer(x.OrigContainer), IOwnMem(x.IOwnMem) { + x.IOwnMem = false; + } + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { OrigContainer = &IP; if (!ProcessInterval(IP.getRootInterval())) { @@ -112,7 +117,7 @@ public: } } - inline ~IntervalIterator() { + ~IntervalIterator() { if (IOwnMem) while (!IntStack.empty()) { delete operator*(); @@ -120,15 +125,17 @@ public: } } - inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;} - inline bool operator!=(const _Self& x) const { return !operator==(x); } + bool operator==(const IntervalIterator &x) const { + return IntStack == x.IntStack; + } + bool operator!=(const IntervalIterator &x) const { return !(*this == x); } - inline const Interval *operator*() const { return IntStack.back().first; } - inline Interval *operator*() { return IntStack.back().first; } - inline const Interval *operator->() const { return operator*(); } - inline Interval *operator->() { return operator*(); } + const Interval *operator*() const { return IntStack.back().first; } + Interval *operator*() { return IntStack.back().first; } + const Interval *operator->() const { return operator*(); } + Interval *operator->() { return operator*(); } - _Self& operator++() { // Preincrement + IntervalIterator &operator++() { // Preincrement assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); do { // All of the intervals on the stack have been visited. Try visiting @@ -150,8 +157,10 @@ public: return *this; } - inline _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; + IntervalIterator operator++(int) { // Postincrement + IntervalIterator tmp = *this; + ++*this; + return tmp; } private: diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h new file mode 100644 index 000000000000..5a339f10f50f --- /dev/null +++ b/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -0,0 +1,96 @@ +//===- IteratedDominanceFrontier.h - Calculate IDF --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \brief Compute iterated dominance frontiers using a linear time algorithm. +/// +/// The algorithm used here is based on: +/// +/// Sreedhar and Gao. A linear time algorithm for placing phi-nodes. +/// In Proceedings of the 22nd ACM SIGPLAN-SIGACT Symposium on Principles of +/// Programming Languages +/// POPL '95. ACM, New York, NY, 62-73. +/// +/// It has been modified to not explicitly use the DJ graph data structure and +/// to directly compute pruned SSA using per-variable liveness information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_IDF_H +#define LLVM_ANALYSIS_IDF_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class BasicBlock; +template <class T> class DomTreeNodeBase; +typedef DomTreeNodeBase<BasicBlock> DomTreeNode; +class DominatorTree; + +/// \brief Determine the iterated dominance frontier, given a set of defining +/// blocks, and optionally, a set of live-in blocks. +/// +/// In turn, the results can be used to place phi nodes. +/// +/// This algorithm is a linear time computation of Iterated Dominance Frontiers, +/// pruned using the live-in set. +/// By default, liveness is not used to prune the IDF computation. +class IDFCalculator { + +public: + IDFCalculator(DominatorTree &DT) : DT(DT), useLiveIn(false) {} + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// defined. This is equivalent to the set of starting blocks it should be + /// calculating the IDF for (though later gets pruned based on liveness). + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + void setDefiningBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { + DefBlocks = &Blocks; + } + + /// \brief Give the IDF calculator the set of blocks in which the value is + /// live on entry to the block. This is used to prune the IDF calculation to + /// not include blocks where any phi insertion would be dead. + /// + /// Note: This set *must* live for the entire lifetime of the IDF calculator. + + void setLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &Blocks) { + LiveInBlocks = &Blocks; + useLiveIn = true; + } + + /// \brief Reset the live-in block set to be empty, and tell the IDF + /// calculator to not use liveness anymore. + void resetLiveInBlocks() { + LiveInBlocks = nullptr; + useLiveIn = false; + } + + /// \brief Calculate iterated dominance frontiers + /// + /// This uses the linear-time phi algorithm based on DJ-graphs mentioned in + /// the file-level comment. It performs DF->IDF pruning using the live-in + /// set, to avoid computing the IDF for blocks where an inserted PHI node + /// would be dead. + void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks); + +private: + DominatorTree &DT; + bool useLiveIn; + DenseMap<DomTreeNode *, unsigned> DomLevels; + const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks; + const SmallPtrSetImpl<BasicBlock *> *DefBlocks; + SmallVector<BasicBlock *, 32> PHIBlocks; +}; +} +#endif diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 591e794a3901..b6dad478cdf2 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -39,7 +39,7 @@ public: /// The default byte alignment for jump tables is 16, which is large but /// usually safe. JumpInstrTableInfo(uint64_t ByteAlign = 16); - virtual ~JumpInstrTableInfo(); + ~JumpInstrTableInfo() override; const char *getPassName() const override { return "Jump-Instruction Table Info"; } diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 9a67d52c3696..1051cff5efb7 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -29,18 +29,17 @@ namespace llvm { /// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { AssumptionCache *AC; - const DataLayout *DL; class TargetLibraryInfo *TLI; DominatorTree *DT; void *PImpl; - LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; - void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; + LazyValueInfo(const LazyValueInfo&) = delete; + void operator=(const LazyValueInfo&) = delete; public: static char ID; LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); } - ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } + ~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); } /// This is used to return true/false/dunno results. enum Tristate { diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index 4c03c922447c..df95e0e6fdc2 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -15,6 +15,7 @@ #define LLVM_ANALYSIS_LIBCALLALIASANALYSIS_H #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/IR/Module.h" #include "llvm/Pass.h" namespace llvm { @@ -35,8 +36,8 @@ namespace llvm { : FunctionPass(ID), LCI(LC) { initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } - ~LibCallAliasAnalysis(); - + ~LibCallAliasAnalysis() override; + ModRefResult getModRefInfo(ImmutableCallSite CS, const Location &Loc) override; @@ -48,11 +49,8 @@ namespace llvm { void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override { - InitializeAliasAnalysis(this); // set up super class - return false; - } - + bool runOnFunction(Function &F) override; + /// getAdjustedAnalysisPointer - This method is used when a pass implements /// an analysis interface through multiple inheritance. If needed, it /// should override this to adjust the this pointer as needed for the diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index 8bd747f03970..34831b2849dd 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -18,6 +18,7 @@ #include "llvm/Analysis/AliasAnalysis.h" namespace llvm { +class InvokeInst; /// LibCallLocationInfo - This struct describes a set of memory locations that /// are accessed by libcalls. Identification of a location is doing with a @@ -162,6 +163,52 @@ namespace llvm { virtual const LibCallFunctionInfo *getFunctionInfoArray() const = 0; }; + enum class EHPersonality { + Unknown, + GNU_Ada, + GNU_C, + GNU_CXX, + GNU_ObjC, + MSVC_X86SEH, + MSVC_Win64SEH, + MSVC_CXX, + }; + + /// \brief See if the given exception handling personality function is one + /// that we understand. If so, return a description of it; otherwise return + /// Unknown. + EHPersonality classifyEHPersonality(const Value *Pers); + + /// \brief Returns true if this personality function catches asynchronous + /// exceptions. + inline bool isAsynchronousEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } + + /// \brief Returns true if this is an MSVC personality function. + inline bool isMSVCEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } + + bool canSimplifyInvokeNoUnwind(const InvokeInst *II); + } // end namespace llvm #endif diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 0fe34539f8f7..42667d2af14a 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -27,8 +27,7 @@ class MDNode; /// specified pointer, we do a quick local scan of the basic block containing /// ScanFrom, to determine if the address is already accessed. bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, - unsigned Align, - const DataLayout *TD = nullptr); + unsigned Align); /// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at /// the instruction before ScanFrom) checking to see if we have the value at diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h new file mode 100644 index 000000000000..c14e1451f338 --- /dev/null +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -0,0 +1,552 @@ +//===- llvm/Analysis/LoopAccessAnalysis.h -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface for the loop memory dependence framework that +// was originally developed for the Loop Vectorizer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOPACCESSANALYSIS_H +#define LLVM_ANALYSIS_LOOPACCESSANALYSIS_H + +#include "llvm/ADT/EquivalenceClasses.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +class Value; +class DataLayout; +class AliasAnalysis; +class ScalarEvolution; +class Loop; +class SCEV; + +/// Optimization analysis message produced during vectorization. Messages inform +/// the user why vectorization did not occur. +class LoopAccessReport { + std::string Message; + const Instruction *Instr; + +protected: + LoopAccessReport(const Twine &Message, const Instruction *I) + : Message(Message.str()), Instr(I) {} + +public: + LoopAccessReport(const Instruction *I = nullptr) : Instr(I) {} + + template <typename A> LoopAccessReport &operator<<(const A &Value) { + raw_string_ostream Out(Message); + Out << Value; + return *this; + } + + const Instruction *getInstr() const { return Instr; } + + std::string &str() { return Message; } + const std::string &str() const { return Message; } + operator Twine() { return Message; } + + /// \brief Emit an analysis note for \p PassName with the debug location from + /// the instruction in \p Message if available. Otherwise use the location of + /// \p TheLoop. + static void emitAnalysis(const LoopAccessReport &Message, + const Function *TheFunction, + const Loop *TheLoop, + const char *PassName); +}; + +/// \brief Collection of parameters shared beetween the Loop Vectorizer and the +/// Loop Access Analysis. +struct VectorizerParams { + /// \brief Maximum SIMD width. + static const unsigned MaxVectorWidth; + + /// \brief VF as overridden by the user. + static unsigned VectorizationFactor; + /// \brief Interleave factor as overridden by the user. + static unsigned VectorizationInterleave; + /// \brief True if force-vector-interleave was specified by the user. + static bool isInterleaveForced(); + + /// \\brief When performing memory disambiguation checks at runtime do not + /// make more than this number of comparisons. + static unsigned RuntimeMemoryCheckThreshold; +}; + +/// \brief Checks memory dependences among accesses to the same underlying +/// object to determine whether there vectorization is legal or not (and at +/// which vectorization factor). +/// +/// Note: This class will compute a conservative dependence for access to +/// different underlying pointers. Clients, such as the loop vectorizer, will +/// sometimes deal these potential dependencies by emitting runtime checks. +/// +/// We use the ScalarEvolution framework to symbolically evalutate access +/// functions pairs. Since we currently don't restructure the loop we can rely +/// on the program order of memory accesses to determine their safety. +/// At the moment we will only deem accesses as safe for: +/// * A negative constant distance assuming program order. +/// +/// Safe: tmp = a[i + 1]; OR a[i + 1] = x; +/// a[i] = tmp; y = a[i]; +/// +/// The latter case is safe because later checks guarantuee that there can't +/// be a cycle through a phi node (that is, we check that "x" and "y" is not +/// the same variable: a header phi can only be an induction or a reduction, a +/// reduction can't have a memory sink, an induction can't have a memory +/// source). This is important and must not be violated (or we have to +/// resort to checking for cycles through memory). +/// +/// * A positive constant distance assuming program order that is bigger +/// than the biggest memory access. +/// +/// tmp = a[i] OR b[i] = x +/// a[i+2] = tmp y = b[i+2]; +/// +/// Safe distance: 2 x sizeof(a[0]), and 2 x sizeof(b[0]), respectively. +/// +/// * Zero distances and all accesses have the same size. +/// +class MemoryDepChecker { +public: + typedef PointerIntPair<Value *, 1, bool> MemAccessInfo; + typedef SmallPtrSet<MemAccessInfo, 8> MemAccessInfoSet; + /// \brief Set of potential dependent memory accesses. + typedef EquivalenceClasses<MemAccessInfo> DepCandidates; + + /// \brief Dependece between memory access instructions. + struct Dependence { + /// \brief The type of the dependence. + enum DepType { + // No dependence. + NoDep, + // We couldn't determine the direction or the distance. + Unknown, + // Lexically forward. + Forward, + // Forward, but if vectorized, is likely to prevent store-to-load + // forwarding. + ForwardButPreventsForwarding, + // Lexically backward. + Backward, + // Backward, but the distance allows a vectorization factor of + // MaxSafeDepDistBytes. + BackwardVectorizable, + // Same, but may prevent store-to-load forwarding. + BackwardVectorizableButPreventsForwarding + }; + + /// \brief String version of the types. + static const char *DepName[]; + + /// \brief Index of the source of the dependence in the InstMap vector. + unsigned Source; + /// \brief Index of the destination of the dependence in the InstMap vector. + unsigned Destination; + /// \brief The type of the dependence. + DepType Type; + + Dependence(unsigned Source, unsigned Destination, DepType Type) + : Source(Source), Destination(Destination), Type(Type) {} + + /// \brief Dependence types that don't prevent vectorization. + static bool isSafeForVectorization(DepType Type); + + /// \brief Dependence types that can be queried from the analysis. + static bool isInterestingDependence(DepType Type); + + /// \brief Lexically backward dependence types. + bool isPossiblyBackward() const; + + /// \brief Print the dependence. \p Instr is used to map the instruction + /// indices to instructions. + void print(raw_ostream &OS, unsigned Depth, + const SmallVectorImpl<Instruction *> &Instrs) const; + }; + + MemoryDepChecker(ScalarEvolution *Se, const Loop *L) + : SE(Se), InnermostLoop(L), AccessIdx(0), + ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true), + RecordInterestingDependences(true) {} + + /// \brief Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(StoreInst *SI) { + Value *Ptr = SI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, true)].push_back(AccessIdx); + InstMap.push_back(SI); + ++AccessIdx; + } + + /// \brief Register the location (instructions are given increasing numbers) + /// of a write access. + void addAccess(LoadInst *LI) { + Value *Ptr = LI->getPointerOperand(); + Accesses[MemAccessInfo(Ptr, false)].push_back(AccessIdx); + InstMap.push_back(LI); + ++AccessIdx; + } + + /// \brief Check whether the dependencies between the accesses are safe. + /// + /// Only checks sets with elements in \p CheckDeps. + bool areDepsSafe(DepCandidates &AccessSets, MemAccessInfoSet &CheckDeps, + const ValueToValueMap &Strides); + + /// \brief No memory dependence was encountered that would inhibit + /// vectorization. + bool isSafeForVectorization() const { return SafeForVectorization; } + + /// \brief The maximum number of bytes of a vector register we can vectorize + /// the accesses safely with. + unsigned getMaxSafeDepDistBytes() { return MaxSafeDepDistBytes; } + + /// \brief In same cases when the dependency check fails we can still + /// vectorize the loop with a dynamic array access check. + bool shouldRetryWithRuntimeCheck() { return ShouldRetryWithRuntimeCheck; } + + /// \brief Returns the interesting dependences. If null is returned we + /// exceeded the MaxInterestingDependence threshold and this information is + /// not available. + const SmallVectorImpl<Dependence> *getInterestingDependences() const { + return RecordInterestingDependences ? &InterestingDependences : nullptr; + } + + void clearInterestingDependences() { InterestingDependences.clear(); } + + /// \brief The vector of memory access instructions. The indices are used as + /// instruction identifiers in the Dependence class. + const SmallVectorImpl<Instruction *> &getMemoryInstructions() const { + return InstMap; + } + + /// \brief Find the set of instructions that read or write via \p Ptr. + SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, + bool isWrite) const; + +private: + ScalarEvolution *SE; + const Loop *InnermostLoop; + + /// \brief Maps access locations (ptr, read/write) to program order. + DenseMap<MemAccessInfo, std::vector<unsigned> > Accesses; + + /// \brief Memory access instructions in program order. + SmallVector<Instruction *, 16> InstMap; + + /// \brief The program order index to be used for the next instruction. + unsigned AccessIdx; + + // We can access this many bytes in parallel safely. + unsigned MaxSafeDepDistBytes; + + /// \brief If we see a non-constant dependence distance we can still try to + /// vectorize this loop with runtime checks. + bool ShouldRetryWithRuntimeCheck; + + /// \brief No memory dependence was encountered that would inhibit + /// vectorization. + bool SafeForVectorization; + + //// \brief True if InterestingDependences reflects the dependences in the + //// loop. If false we exceeded MaxInterestingDependence and + //// InterestingDependences is invalid. + bool RecordInterestingDependences; + + /// \brief Interesting memory dependences collected during the analysis as + /// defined by isInterestingDependence. Only valid if + /// RecordInterestingDependences is true. + SmallVector<Dependence, 8> InterestingDependences; + + /// \brief Check whether there is a plausible dependence between the two + /// accesses. + /// + /// Access \p A must happen before \p B in program order. The two indices + /// identify the index into the program order map. + /// + /// This function checks whether there is a plausible dependence (or the + /// absence of such can't be proved) between the two accesses. If there is a + /// plausible dependence but the dependence distance is bigger than one + /// element access it records this distance in \p MaxSafeDepDistBytes (if this + /// distance is smaller than any other distance encountered so far). + /// Otherwise, this function returns true signaling a possible dependence. + Dependence::DepType isDependent(const MemAccessInfo &A, unsigned AIdx, + const MemAccessInfo &B, unsigned BIdx, + const ValueToValueMap &Strides); + + /// \brief Check whether the data dependence could prevent store-load + /// forwarding. + bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize); +}; + +/// \brief Drive the analysis of memory accesses in the loop +/// +/// This class is responsible for analyzing the memory accesses of a loop. It +/// collects the accesses and then its main helper the AccessAnalysis class +/// finds and categorizes the dependences in buildDependenceSets. +/// +/// For memory dependences that can be analyzed at compile time, it determines +/// whether the dependence is part of cycle inhibiting vectorization. This work +/// is delegated to the MemoryDepChecker class. +/// +/// For memory dependences that cannot be determined at compile time, it +/// generates run-time checks to prove independence. This is done by +/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the +/// RuntimePointerCheck class. +class LoopAccessInfo { +public: + /// This struct holds information about the memory runtime legality check that + /// a group of pointers do not overlap. + struct RuntimePointerCheck { + RuntimePointerCheck() : Need(false) {} + + /// Reset the state of the pointer runtime information. + void reset() { + Need = false; + Pointers.clear(); + Starts.clear(); + Ends.clear(); + IsWritePtr.clear(); + DependencySetId.clear(); + AliasSetId.clear(); + } + + /// Insert a pointer and calculate the start and end SCEVs. + void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, + unsigned DepSetId, unsigned ASId, + const ValueToValueMap &Strides); + + /// \brief No run-time memory checking is necessary. + bool empty() const { return Pointers.empty(); } + + /// \brief Decide whether we need to issue a run-time check for pointer at + /// index \p I and \p J to prove their independence. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + bool needsChecking(unsigned I, unsigned J, + const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Return true if any pointer requires run-time checking according + /// to needsChecking. + bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; + + /// \brief Print the list run-time memory checks necessary. + /// + /// If \p PtrPartition is set, it contains the partition number for + /// pointers (-1 if the pointer belongs to multiple partitions). In this + /// case omit checks between pointers belonging to the same partition. + void print(raw_ostream &OS, unsigned Depth = 0, + const SmallVectorImpl<int> *PtrPartition = nullptr) const; + + /// This flag indicates if we need to add the runtime check. + bool Need; + /// Holds the pointers that we need to check. + SmallVector<TrackingVH<Value>, 2> Pointers; + /// Holds the pointer value at the beginning of the loop. + SmallVector<const SCEV*, 2> Starts; + /// Holds the pointer value at the end of the loop. + SmallVector<const SCEV*, 2> Ends; + /// Holds the information if this pointer is used for writing to memory. + SmallVector<bool, 2> IsWritePtr; + /// Holds the id of the set of pointers that could be dependent because of a + /// shared underlying object. + SmallVector<unsigned, 2> DependencySetId; + /// Holds the id of the disjoint alias set to which this pointer belongs. + SmallVector<unsigned, 2> AliasSetId; + }; + + LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, + const TargetLibraryInfo *TLI, AliasAnalysis *AA, + DominatorTree *DT, LoopInfo *LI, + const ValueToValueMap &Strides); + + /// Return true we can analyze the memory accesses in the loop and there are + /// no memory dependence cycles. + bool canVectorizeMemory() const { return CanVecMem; } + + const RuntimePointerCheck *getRuntimePointerCheck() const { + return &PtrRtCheck; + } + + /// \brief Number of memchecks required to prove independence of otherwise + /// may-alias pointers. + unsigned getNumRuntimePointerChecks() const { return NumComparisons; } + + /// Return true if the block BB needs to be predicated in order for the loop + /// to be vectorized. + static bool blockNeedsPredication(BasicBlock *BB, Loop *TheLoop, + DominatorTree *DT); + + /// Returns true if the value V is uniform within the loop. + bool isUniform(Value *V) const; + + unsigned getMaxSafeDepDistBytes() const { return MaxSafeDepDistBytes; } + unsigned getNumStores() const { return NumStores; } + unsigned getNumLoads() const { return NumLoads;} + + /// \brief Add code that checks at runtime if the accessed arrays overlap. + /// + /// Returns a pair of instructions where the first element is the first + /// instruction generated in possibly a sequence of instructions and the + /// second value is the final comparator value or NULL if no check is needed. + /// + /// If \p PtrPartition is set, it contains the partition number for pointers + /// (-1 if the pointer belongs to multiple partitions). In this case omit + /// checks between pointers belonging to the same partition. + std::pair<Instruction *, Instruction *> + addRuntimeCheck(Instruction *Loc, + const SmallVectorImpl<int> *PtrPartition = nullptr) const; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + const Optional<LoopAccessReport> &getReport() const { return Report; } + + /// \brief the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + const MemoryDepChecker &getDepChecker() const { return DepChecker; } + + /// \brief Return the list of instructions that use \p Ptr to read or write + /// memory. + SmallVector<Instruction *, 4> getInstructionsForAccess(Value *Ptr, + bool isWrite) const { + return DepChecker.getInstructionsForAccess(Ptr, isWrite); + } + + /// \brief Print the information about the memory accesses in the loop. + void print(raw_ostream &OS, unsigned Depth = 0) const; + + /// \brief Used to ensure that if the analysis was run with speculating the + /// value of symbolic strides, the client queries it with the same assumption. + /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI. + unsigned NumSymbolicStrides; + + /// \brief Checks existence of store to invariant address inside loop. + /// If the loop has any store to invariant address, then it returns true, + /// else returns false. + bool hasStoreToLoopInvariantAddress() const { + return StoreToLoopInvariantAddress; + } + +private: + /// \brief Analyze the loop. Substitute symbolic strides using Strides. + void analyzeLoop(const ValueToValueMap &Strides); + + /// \brief Check if the structure of the loop allows it to be analyzed by this + /// pass. + bool canAnalyzeLoop(); + + void emitAnalysis(LoopAccessReport &Message); + + /// We need to check that all of the pointers in this list are disjoint + /// at runtime. + RuntimePointerCheck PtrRtCheck; + + /// \brief the Memory Dependence Checker which can determine the + /// loop-independent and loop-carried dependences between memory accesses. + MemoryDepChecker DepChecker; + + /// \brief Number of memchecks required to prove independence of otherwise + /// may-alias pointers + unsigned NumComparisons; + + Loop *TheLoop; + ScalarEvolution *SE; + const DataLayout &DL; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + LoopInfo *LI; + + unsigned NumLoads; + unsigned NumStores; + + unsigned MaxSafeDepDistBytes; + + /// \brief Cache the result of analyzeLoop. + bool CanVecMem; + + /// \brief Indicator for storing to uniform addresses. + /// If a loop has write to a loop invariant address then it should be true. + bool StoreToLoopInvariantAddress; + + /// \brief The diagnostics report generated for the analysis. E.g. why we + /// couldn't analyze the loop. + Optional<LoopAccessReport> Report; +}; + +Value *stripIntegerCast(Value *V); + +///\brief Return the SCEV corresponding to a pointer with the symbolic stride +///replaced with constant one. +/// +/// If \p OrigPtr is not null, use it to look up the stride value instead of \p +/// Ptr. \p PtrToStride provides the mapping between the pointer value and its +/// stride as collected by LoopVectorizationLegality::collectStridedAccess. +const SCEV *replaceSymbolicStrideSCEV(ScalarEvolution *SE, + const ValueToValueMap &PtrToStride, + Value *Ptr, Value *OrigPtr = nullptr); + +/// \brief This analysis provides dependence information for the memory accesses +/// of a loop. +/// +/// It runs the analysis for a loop on demand. This can be initiated by +/// querying the loop access info via LAA::getInfo. getInfo return a +/// LoopAccessInfo object. See this class for the specifics of what information +/// is provided. +class LoopAccessAnalysis : public FunctionPass { +public: + static char ID; + + LoopAccessAnalysis() : FunctionPass(ID) { + initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + /// \brief Query the result of the loop access information for the loop \p L. + /// + /// If the client speculates (and then issues run-time checks) for the values + /// of symbolic strides, \p Strides provides the mapping (see + /// replaceSymbolicStrideSCEV). If there is no cached result available run + /// the analysis. + const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + + void releaseMemory() override { + // Invalidate the cache when the pass is freed. + LoopAccessInfoMap.clear(); + } + + /// \brief Print the result of the analysis when invoked with -analyze. + void print(raw_ostream &OS, const Module *M = nullptr) const override; + +private: + /// \brief The cache. + DenseMap<Loop *, std::unique_ptr<LoopAccessInfo>> LoopAccessInfoMap; + + // The used analysis passes. + ScalarEvolution *SE; + const TargetLibraryInfo *TLI; + AliasAnalysis *AA; + DominatorTree *DT; + LoopInfo *LI; +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index bef03e91bbbd..be78c15e7224 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -42,6 +42,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template <typename IRUnitT> class AnalysisManager; +class PreservedAnalyses; + template<typename T> inline void RemoveFromVector(std::vector<T*> &V, T *N) { typename std::vector<T*>::iterator I = std::find(V.begin(), V.end(), N); @@ -74,9 +79,9 @@ class LoopBase { SmallPtrSet<const BlockT*, 8> DenseBlockSet; - LoopBase(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; + LoopBase(const LoopBase<BlockT, LoopT> &) = delete; const LoopBase<BlockT, LoopT>& - operator=(const LoopBase<BlockT, LoopT> &) LLVM_DELETED_FUNCTION; + operator=(const LoopBase<BlockT, LoopT> &) = delete; public: /// Loop ctor - This creates an empty loop. LoopBase() : ParentLoop(nullptr) {} @@ -356,11 +361,11 @@ public: /// isLoopInvariant - Return true if the specified value is loop invariant /// - bool isLoopInvariant(Value *V) const; + bool isLoopInvariant(const Value *V) const; /// hasLoopInvariantOperands - Return true if all the operands of the /// specified instruction are loop invariant. - bool hasLoopInvariantOperands(Instruction *I) const; + bool hasLoopInvariantOperands(const Instruction *I) const; /// makeLoopInvariant - If the given value is an instruction inside of the /// loop and it can be hoisted, do so to make it trivially loop-invariant. @@ -459,23 +464,20 @@ public: /// cannot find a terminating instruction with location information, /// it returns an unknown location. DebugLoc getStartLoc() const { - DebugLoc StartLoc; BasicBlock *HeadBB; // Try the pre-header first. - if ((HeadBB = getLoopPreheader()) != nullptr) { - StartLoc = HeadBB->getTerminator()->getDebugLoc(); - if (!StartLoc.isUnknown()) - return StartLoc; - } + if ((HeadBB = getLoopPreheader()) != nullptr) + if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc()) + return DL; // If we have no pre-header or there are no instructions with debug // info in it, try the header. HeadBB = getHeader(); if (HeadBB) - StartLoc = HeadBB->getTerminator()->getDebugLoc(); + return HeadBB->getTerminator()->getDebugLoc(); - return StartLoc; + return DebugLoc(); } private: @@ -496,18 +498,33 @@ class LoopInfoBase { friend class LoopBase<BlockT, LoopT>; friend class LoopInfo; - void operator=(const LoopInfoBase &) LLVM_DELETED_FUNCTION; - LoopInfoBase(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfoBase &) = delete; + LoopInfoBase(const LoopInfoBase &) = delete; public: LoopInfoBase() { } ~LoopInfoBase() { releaseMemory(); } + LoopInfoBase(LoopInfoBase &&Arg) + : BBMap(std::move(Arg.BBMap)), + TopLevelLoops(std::move(Arg.TopLevelLoops)) { + // We have to clear the arguments top level loops as we've taken ownership. + Arg.TopLevelLoops.clear(); + } + LoopInfoBase &operator=(LoopInfoBase &&RHS) { + BBMap = std::move(RHS.BBMap); + + for (auto *L : TopLevelLoops) + delete L; + TopLevelLoops = std::move(RHS.TopLevelLoops); + RHS.TopLevelLoops.clear(); + return *this; + } + void releaseMemory() { - for (typename std::vector<LoopT *>::iterator I = - TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) - delete *I; // Delete all of the loops... + BBMap.clear(); - BBMap.clear(); // Reset internal state of analysis + for (auto *L : TopLevelLoops) + delete L; TopLevelLoops.clear(); } @@ -576,8 +593,7 @@ public: /// list with the indicated loop. void changeTopLevelLoop(LoopT *OldLoop, LoopT *NewLoop) { - typename std::vector<LoopT *>::iterator I = - std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); + auto I = std::find(TopLevelLoops.begin(), TopLevelLoops.end(), OldLoop); assert(I != TopLevelLoops.end() && "Old loop not at top level!"); *I = NewLoop; assert(!NewLoop->ParentLoop && !OldLoop->ParentLoop && @@ -595,7 +611,7 @@ public: /// including all of the Loop objects it is nested in and our mapping from /// BasicBlocks to loops. void removeBlock(BlockT *BB) { - typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB); + auto I = BBMap.find(BB); if (I != BBMap.end()) { for (LoopT *L = I->second; L; L = L->getParentLoop()) L->removeBlockFromLoop(BB); @@ -617,8 +633,9 @@ public: void Analyze(DominatorTreeBase<BlockT> &DomTree); // Debugging - void print(raw_ostream &OS) const; + + void verify() const; }; // Implementation in LoopInfoImpl.h @@ -626,99 +643,23 @@ public: __extension__ extern template class LoopInfoBase<BasicBlock, Loop>; #endif -class LoopInfo : public FunctionPass { - LoopInfoBase<BasicBlock, Loop> LI; +class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { + typedef LoopInfoBase<BasicBlock, Loop> BaseT; + friend class LoopBase<BasicBlock, Loop>; - void operator=(const LoopInfo &) LLVM_DELETED_FUNCTION; - LoopInfo(const LoopInfo &) LLVM_DELETED_FUNCTION; + void operator=(const LoopInfo &) = delete; + LoopInfo(const LoopInfo &) = delete; public: - static char ID; // Pass identification, replacement for typeid - - LoopInfo() : FunctionPass(ID) { - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - } - - LoopInfoBase<BasicBlock, Loop>& getBase() { return LI; } - - /// iterator/begin/end - The interface to the top-level loops in the current - /// function. - /// - typedef LoopInfoBase<BasicBlock, Loop>::iterator iterator; - typedef LoopInfoBase<BasicBlock, Loop>::reverse_iterator reverse_iterator; - inline iterator begin() const { return LI.begin(); } - inline iterator end() const { return LI.end(); } - inline reverse_iterator rbegin() const { return LI.rbegin(); } - inline reverse_iterator rend() const { return LI.rend(); } - bool empty() const { return LI.empty(); } - - /// getLoopFor - Return the inner most loop that BB lives in. If a basic - /// block is in no loop (for example the entry node), null is returned. - /// - inline Loop *getLoopFor(const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// operator[] - same as getLoopFor... - /// - inline const Loop *operator[](const BasicBlock *BB) const { - return LI.getLoopFor(BB); - } - - /// getLoopDepth - Return the loop nesting level of the specified block. A - /// depth of 0 means the block is not inside any loop. - /// - inline unsigned getLoopDepth(const BasicBlock *BB) const { - return LI.getLoopDepth(BB); - } - - // isLoopHeader - True if the block is a loop header node - inline bool isLoopHeader(BasicBlock *BB) const { - return LI.isLoopHeader(BB); - } - - /// runOnFunction - Calculate the natural loop information. - /// - bool runOnFunction(Function &F) override; - - void verifyAnalysis() const override; - - void releaseMemory() override { LI.releaseMemory(); } - - void print(raw_ostream &O, const Module* M = nullptr) const override; - - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// removeLoop - This removes the specified top-level loop from this loop info - /// object. The loop is not deleted, as it will presumably be inserted into - /// another loop. - inline Loop *removeLoop(iterator I) { return LI.removeLoop(I); } - - /// changeLoopFor - Change the top-level loop that contains BB to the - /// specified loop. This should be used by transformations that restructure - /// the loop hierarchy tree. - inline void changeLoopFor(BasicBlock *BB, Loop *L) { - LI.changeLoopFor(BB, L); - } + LoopInfo() {} - /// changeTopLevelLoop - Replace the specified loop in the top-level loops - /// list with the indicated loop. - inline void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop) { - LI.changeTopLevelLoop(OldLoop, NewLoop); - } - - /// addTopLevelLoop - This adds the specified loop to the collection of - /// top-level loops. - inline void addTopLevelLoop(Loop *New) { - LI.addTopLevelLoop(New); + LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + LoopInfo &operator=(LoopInfo &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; } - /// removeBlock - This method completely removes BB from all data structures, - /// including all of the Loop objects it is nested in and our mapping from - /// BasicBlocks to loops. - void removeBlock(BasicBlock *BB) { - LI.removeBlock(BB); - } + // Most of the public interface is provided via LoopInfoBase. /// updateUnloop - Update LoopInfo after removing the last backedge from a /// loop--now the "unloop". This updates the loop forest and parent loops for @@ -748,7 +689,6 @@ public: } }; - // Allow clients to walk the list of nested loops... template <> struct GraphTraits<const Loop*> { typedef const Loop NodeType; @@ -776,6 +716,65 @@ template <> struct GraphTraits<Loop*> { } }; +/// \brief Analysis pass that exposes the \c LoopInfo for a function. +class LoopAnalysis { + static char PassID; + +public: + typedef LoopInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide a name for the analysis for debugging and logging. + static StringRef name() { return "LoopAnalysis"; } + + LoopAnalysis() {} + LoopAnalysis(const LoopAnalysis &Arg) {} + LoopAnalysis(LoopAnalysis &&Arg) {} + LoopAnalysis &operator=(const LoopAnalysis &RHS) { return *this; } + LoopAnalysis &operator=(LoopAnalysis &&RHS) { return *this; } + + LoopInfo run(Function &F, AnalysisManager<Function> *AM); +}; + +/// \brief Printer pass for the \c LoopAnalysis results. +class LoopPrinterPass { + raw_ostream &OS; + +public: + explicit LoopPrinterPass(raw_ostream &OS) : OS(OS) {} + PreservedAnalyses run(Function &F, AnalysisManager<Function> *AM); + + static StringRef name() { return "LoopPrinterPass"; } +}; + +/// \brief The legacy pass manager's analysis pass to compute loop information. +class LoopInfoWrapperPass : public FunctionPass { + LoopInfo LI; + +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfoWrapperPass() : FunctionPass(ID) { + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + LoopInfo &getLoopInfo() { return LI; } + const LoopInfo &getLoopInfo() const { return LI; } + + /// \brief Calculate the natural loop information for a given function. + bool runOnFunction(Function &F) override; + + void verifyAnalysis() const override; + + void releaseMemory() override { LI.releaseMemory(); } + + void print(raw_ostream &O, const Module *M = nullptr) const override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; +}; + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 948be0f5ee1e..0490bb1d761a 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -402,7 +402,6 @@ static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, L->reserveBlocks(NumBlocks); } -namespace { /// Populate all loop data in a stable order during a single forward DFS. template<class BlockT, class LoopT> class PopulateLoopsDFS { @@ -410,9 +409,6 @@ class PopulateLoopsDFS { typedef typename BlockTraits::ChildIteratorType SuccIterTy; LoopInfoBase<BlockT, LoopT> *LI; - DenseSet<const BlockT *> VisitedBlocks; - std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack; - public: PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li): LI(li) {} @@ -421,37 +417,13 @@ public: protected: void insertIntoLoop(BlockT *Block); - - BlockT *dfsSource() { return DFSStack.back().first; } - SuccIterTy &dfsSucc() { return DFSStack.back().second; } - SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); } - - void pushBlock(BlockT *Block) { - DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block))); - } }; -} // anonymous /// Top-level driver for the forward DFS within the loop. template<class BlockT, class LoopT> void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) { - pushBlock(EntryBlock); - VisitedBlocks.insert(EntryBlock); - while (!DFSStack.empty()) { - // Traverse the leftmost path as far as possible. - while (dfsSucc() != dfsSuccEnd()) { - BlockT *BB = *dfsSucc(); - ++dfsSucc(); - if (!VisitedBlocks.insert(BB).second) - continue; - - // Push the next DFS successor onto the stack. - pushBlock(BB); - } - // Visit the top of the stack in postorder and backtrack. - insertIntoLoop(dfsSource()); - DFSStack.pop_back(); - } + for (BlockT *BB : post_order(EntryBlock)) + insertIntoLoop(BB); } /// Add a single Block to its ancestor loops in PostOrder. If the block is a @@ -500,10 +472,9 @@ Analyze(DominatorTreeBase<BlockT> &DomTree) { // Postorder traversal of the dominator tree. DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode(); - for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot), - DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) { + for (auto DomNode : post_order(DomRoot)) { - BlockT *Header = DomIter->getBlock(); + BlockT *Header = DomNode->getBlock(); SmallVector<BlockT *, 4> Backedges; // Check each predecessor of the potential loop header. @@ -545,6 +516,25 @@ void LoopInfoBase<BlockT, LoopT>::print(raw_ostream &OS) const { #endif } +template<class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::verify() const { + DenseSet<const LoopT*> Loops; + for (iterator I = begin(), E = end(); I != E; ++I) { + assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); + (*I)->verifyLoopNest(&Loops); + } + + // Verify that blocks are mapped to valid loops. +#ifndef NDEBUG + for (auto &Entry : BBMap) { + BlockT *BB = Entry.first; + LoopT *L = Entry.second; + assert(Loops.count(L) && "orphaned loop"); + assert(L->contains(BB) && "orphaned block"); + } +#endif +} + } // End llvm namespace #endif diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index d414680b519d..805a43dfb070 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -82,12 +82,6 @@ static inline CallInst *extractMallocCall(Value *I, return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI)); } -/// isArrayMalloc - Returns the corresponding CallInst if the instruction -/// is a call to malloc whose array size can be determined and the array size -/// is not constant 1. Otherwise, return NULL. -const CallInst *isArrayMalloc(const Value *I, const DataLayout *DL, - const TargetLibraryInfo *TLI); - /// getMallocType - Returns the PointerType resulting from the malloc call. /// The PointerType depends on the number of bitcast uses of the malloc call: /// 0: PointerType is the malloc calls' return type. @@ -107,11 +101,10 @@ Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); /// then return that multiple. For non-array mallocs, the multiple is /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be /// determined. -Value *getMallocArraySize(CallInst *CI, const DataLayout *DL, +Value *getMallocArraySize(CallInst *CI, const DataLayout &DL, const TargetLibraryInfo *TLI, bool LookThroughSExt = false); - //===----------------------------------------------------------------------===// // calloc Call Utility Functions. // @@ -147,11 +140,9 @@ static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { /// underlying object pointed to by Ptr. /// If RoundToAlign is true, then Size is rounded up to the aligment of allocas, /// byval arguments, and global variables. -bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *DL, +bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout &DL, const TargetLibraryInfo *TLI, bool RoundToAlign = false); - - typedef std::pair<APInt, APInt> SizeOffsetType; /// \brief Evaluate the size and offset of an object pointed to by a Value* @@ -159,7 +150,7 @@ typedef std::pair<APInt, APInt> SizeOffsetType; class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { - const DataLayout *DL; + const DataLayout &DL; const TargetLibraryInfo *TLI; bool RoundToAlign; unsigned IntTyBits; @@ -173,7 +164,7 @@ class ObjectSizeOffsetVisitor } public: - ObjectSizeOffsetVisitor(const DataLayout *DL, const TargetLibraryInfo *TLI, + ObjectSizeOffsetVisitor(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetType compute(Value *V); @@ -222,7 +213,7 @@ class ObjectSizeOffsetEvaluator typedef DenseMap<const Value*, WeakEvalType> CacheMapTy; typedef SmallPtrSet<const Value*, 8> PtrSetTy; - const DataLayout *DL; + const DataLayout &DL; const TargetLibraryInfo *TLI; LLVMContext &Context; BuilderTy Builder; @@ -238,7 +229,7 @@ class ObjectSizeOffsetEvaluator SizeOffsetEvalType compute_(Value *V); public: - ObjectSizeOffsetEvaluator(const DataLayout *DL, const TargetLibraryInfo *TLI, + ObjectSizeOffsetEvaluator(const DataLayout &DL, const TargetLibraryInfo *TLI, LLVMContext &Context, bool RoundToAlign = false); SizeOffsetEvalType compute(Value *V); diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 67fd70a4561f..cf51dd62388f 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/IR/BasicBlock.h" +#include "llvm/IR/PredIteratorCache.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" @@ -29,7 +30,6 @@ namespace llvm { class CallSite; class AliasAnalysis; class AssumptionCache; - class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; class DominatorTree; @@ -324,14 +324,13 @@ namespace llvm { /// Current AA implementation, just a cache. AliasAnalysis *AA; - const DataLayout *DL; DominatorTree *DT; AssumptionCache *AC; - std::unique_ptr<PredIteratorCache> PredCache; + PredIteratorCache PredCache; public: MemoryDependenceAnalysis(); - ~MemoryDependenceAnalysis(); + ~MemoryDependenceAnalysis() override; static char ID; /// Pass Implementation stuff. This doesn't do any analysis eagerly. @@ -421,20 +420,21 @@ namespace llvm { static unsigned getLoadLoadClobberFullWidthSize(const Value *MemLocBase, int64_t MemLocOffs, unsigned MemLocSize, - const LoadInst *LI, - const DataLayout &DL); + const LoadInst *LI); private: MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall, BasicBlock::iterator ScanIt, BasicBlock *BB); - bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, + bool getNonLocalPointerDepFromBB(Instruction *QueryInst, + const PHITransAddr &Pointer, const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, SmallVectorImpl<NonLocalDepResult> &Result, DenseMap<BasicBlock*, Value*> &Visited, bool SkipFirstBlock = false); - MemDepResult GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc, + MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst, + const AliasAnalysis::Location &Loc, bool isLoad, BasicBlock *BB, NonLocalDepInfo *Cache, unsigned NumSortedEntries); diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 38730d8ea4f3..84bb9d8008b5 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -36,9 +36,9 @@ namespace llvm { class PHITransAddr { /// Addr - The actual address we're analyzing. Value *Addr; - - /// The DataLayout we are playing with if known, otherwise null. - const DataLayout *DL; + + /// The DataLayout we are playing with. + const DataLayout &DL; /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; @@ -49,7 +49,7 @@ class PHITransAddr { /// InstInputs - The inputs for our symbolic address. SmallVector<Instruction*, 4> InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + PHITransAddr(Value *addr, const DataLayout &DL, AssumptionCache *AC) : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast<Instruction>(Addr)) diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 10a56059ae10..d112ab1823b4 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -138,6 +138,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createDivergenceAnalysisPass - This pass determines which branches in a GPU + // program are divergent. + // + FunctionPass *createDivergenceAnalysisPass(); + + //===--------------------------------------------------------------------===// + // // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); @@ -159,9 +166,13 @@ namespace llvm { // FunctionPass *createMemDepPrinter(); - // createJumpInstrTableInfoPass - This creates a pass that stores information - // about the jump tables created by JumpInstrTables - ImmutablePass *createJumpInstrTableInfoPass(); + //===--------------------------------------------------------------------===// + // + // createMemDerefPrinter - This pass collects memory dereferenceability + // information and prints it with -analyze. + // + FunctionPass *createMemDerefPrinter(); + } #endif diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 72cd35754c8a..0f7e2b88d2d7 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -30,7 +30,7 @@ struct PostDominatorTree : public FunctionPass { DT = new DominatorTreeBase<BasicBlock>(true); } - ~PostDominatorTree(); + ~PostDominatorTree() override; bool runOnFunction(Function &F) override; diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 6ff7f97d01f5..7ceb086ee0a1 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -115,8 +115,8 @@ public: typedef typename Tr::RegionT RegionT; private: - RegionNodeBase(const RegionNodeBase &) LLVM_DELETED_FUNCTION; - const RegionNodeBase &operator=(const RegionNodeBase &) LLVM_DELETED_FUNCTION; + RegionNodeBase(const RegionNodeBase &) = delete; + const RegionNodeBase &operator=(const RegionNodeBase &) = delete; /// This is the entry basic block that starts this region node. If this is a /// BasicBlock RegionNode, then entry is just the basic block, that this @@ -261,8 +261,8 @@ class RegionBase : public RegionNodeBase<Tr> { typedef typename InvBlockTraits::ChildIteratorType PredIterTy; friend class RegionInfoBase<Tr>; - RegionBase(const RegionBase &) LLVM_DELETED_FUNCTION; - const RegionBase &operator=(const RegionBase &) LLVM_DELETED_FUNCTION; + RegionBase(const RegionBase &) = delete; + const RegionBase &operator=(const RegionBase &) = delete; // Information necessary to manage this Region. RegionInfoT *RI; @@ -674,8 +674,8 @@ class RegionInfoBase { RegionInfoBase(); virtual ~RegionInfoBase(); - RegionInfoBase(const RegionInfoBase &) LLVM_DELETED_FUNCTION; - const RegionInfoBase &operator=(const RegionInfoBase &) LLVM_DELETED_FUNCTION; + RegionInfoBase(const RegionInfoBase &) = delete; + const RegionInfoBase &operator=(const RegionInfoBase &) = delete; DomTreeT *DT; PostDomTreeT *PDT; @@ -820,8 +820,6 @@ public: inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {} - ~RegionNode() {} - bool operator==(const Region &RN) const { return this == reinterpret_cast<const RegionNode *>(&RN); } @@ -842,7 +840,7 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> { public: explicit RegionInfo(); - virtual ~RegionInfo(); + ~RegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; @@ -858,7 +856,7 @@ public: static char ID; explicit RegionInfoPass(); - ~RegionInfoPass(); + ~RegionInfoPass() override; RegionInfo &getRegionInfo() { return RI; } diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index b0dc26312aaa..b31eefc15f78 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -487,7 +487,7 @@ void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level, OS.indent(level * 2 + 2); if (Style == PrintBB) { - for (const auto &BB : blocks()) + for (const auto *BB : blocks()) OS << BB->getName() << ", "; // TODO: remove the last "," } else if (Style == PrintRN) { for (const_element_iterator I = element_begin(), E = element_end(); @@ -714,10 +714,8 @@ void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { // regions from the bottom of the dominance tree. If the small regions are // detected first, detection of bigger regions is faster, as we can jump // over the small regions. - for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE; - ++FI) { - findRegionsWithEntry(FI->getBlock(), ShortCut); - } + for (auto DomNode : post_order(N)) + findRegionsWithEntry(DomNode->getBlock(), ShortCut); } template <class Tr> diff --git a/include/llvm/Analysis/RegionIterator.h b/include/llvm/Analysis/RegionIterator.h index 0daff58475dd..ced58dfabdd5 100644 --- a/include/llvm/Analysis/RegionIterator.h +++ b/include/llvm/Analysis/RegionIterator.h @@ -145,16 +145,6 @@ public: ++*this; return tmp; } - - inline const Self &operator=(const Self &I) { - if (this != &I) { - assert(getNode()->getParent() == I.getNode()->getParent() - && "Cannot assign iterators of two different regions!"); - Node = I.Node; - BItor = I.BItor; - } - return *this; - } }; @@ -240,16 +230,6 @@ public: ++*this; return tmp; } - - inline const Self &operator=(const Self &I) { - if (this != &I) { - assert(Node->getParent() == I.Node->getParent() - && "Cannot assign iterators to two different regions!"); - Node = I.Node; - Itor = I.Itor; - } - return *this; - } }; template<class NodeType, class BlockT, class RegionT> diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index f394e335257f..1d1bd67b61ff 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -71,8 +71,8 @@ namespace llvm { unsigned short SubclassData; private: - SCEV(const SCEV &) LLVM_DELETED_FUNCTION; - void operator=(const SCEV &) LLVM_DELETED_FUNCTION; + SCEV(const SCEV &) = delete; + void operator=(const SCEV &) = delete; public: /// NoWrapFlags are bitfield indices into SubclassData. @@ -82,12 +82,13 @@ namespace llvm { /// operator. NSW is a misnomer that we use to mean no signed overflow or /// underflow. /// - /// AddRec expression may have a no-self-wraparound <NW> property if the - /// result can never reach the start value. This property is independent of - /// the actual start value and step direction. Self-wraparound is defined - /// purely in terms of the recurrence's loop, step size, and - /// bitwidth. Formally, a recurrence with no self-wraparound satisfies: - /// abs(step) * max-iteration(loop) <= unsigned-max(bitwidth). + /// AddRec expressions may have a no-self-wraparound <NW> property if, in + /// the integer domain, abs(step) * max-iteration(loop) <= + /// unsigned-max(bitwidth). This means that the recurrence will never reach + /// its start value if the step is non-zero. Computing the same value on + /// each iteration is not considered wrapping, and recurrences with step = 0 + /// are trivially <NW>. <NW> is independent of the sign of step and the + /// value the add recurrence starts with. /// /// Note that NUW and NSW are also valid properties of a recurrence, and /// either implies NW. For convenience, NW will be set for a recurrence @@ -231,10 +232,6 @@ namespace llvm { /// LoopInfo *LI; - /// The DataLayout information for the target we are targeting. - /// - const DataLayout *DL; - /// TLI - The target library information for the target we are targeting. /// TargetLibraryInfo *TLI; @@ -259,6 +256,10 @@ namespace llvm { /// Mark predicate values currently being processed by isImpliedCond. DenseSet<Value*> PendingLoopPredicates; + /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of + /// conditions dominating the backedge of a loop. + bool WalkingBEDominatingConds; + /// ExitLimit - Information about the number of loop iterations for which a /// loop exit's branch condition evaluates to the not-taken path. This is a /// temporary pair of exact and max expressions that are eventually @@ -372,44 +373,46 @@ namespace llvm { /// LoopDispositions - Memoized computeLoopDisposition results. DenseMap<const SCEV *, - SmallVector<std::pair<const Loop *, LoopDisposition>, 2> > LoopDispositions; + SmallVector<PointerIntPair<const Loop *, 2, LoopDisposition>, 2>> + LoopDispositions; /// computeLoopDisposition - Compute a LoopDisposition value. LoopDisposition computeLoopDisposition(const SCEV *S, const Loop *L); /// BlockDispositions - Memoized computeBlockDisposition results. - DenseMap<const SCEV *, - SmallVector<std::pair<const BasicBlock *, BlockDisposition>, 2> > BlockDispositions; + DenseMap< + const SCEV *, + SmallVector<PointerIntPair<const BasicBlock *, 2, BlockDisposition>, 2>> + BlockDispositions; /// computeBlockDisposition - Compute a BlockDisposition value. BlockDisposition computeBlockDisposition(const SCEV *S, const BasicBlock *BB); - /// UnsignedRanges - Memoized results from getUnsignedRange + /// UnsignedRanges - Memoized results from getRange DenseMap<const SCEV *, ConstantRange> UnsignedRanges; - /// SignedRanges - Memoized results from getSignedRange + /// SignedRanges - Memoized results from getRange DenseMap<const SCEV *, ConstantRange> SignedRanges; - /// setUnsignedRange - Set the memoized unsigned range for the given SCEV. - const ConstantRange &setUnsignedRange(const SCEV *S, - const ConstantRange &CR) { - std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = - UnsignedRanges.insert(std::make_pair(S, CR)); - if (!Pair.second) - Pair.first->second = CR; - return Pair.first->second; - } + /// RangeSignHint - Used to parameterize getRange + enum RangeSignHint { HINT_RANGE_UNSIGNED, HINT_RANGE_SIGNED }; + + /// setRange - Set the memoized range for the given SCEV. + const ConstantRange &setRange(const SCEV *S, RangeSignHint Hint, + const ConstantRange &CR) { + DenseMap<const SCEV *, ConstantRange> &Cache = + Hint == HINT_RANGE_UNSIGNED ? UnsignedRanges : SignedRanges; - /// setUnsignedRange - Set the memoized signed range for the given SCEV. - const ConstantRange &setSignedRange(const SCEV *S, - const ConstantRange &CR) { std::pair<DenseMap<const SCEV *, ConstantRange>::iterator, bool> Pair = - SignedRanges.insert(std::make_pair(S, CR)); + Cache.insert(std::make_pair(S, CR)); if (!Pair.second) Pair.first->second = CR; return Pair.first->second; } + /// getRange - Determine the range for a particular SCEV. + ConstantRange getRange(const SCEV *S, RangeSignHint Hint); + /// createSCEV - We know that there is no SCEV for the specified value. /// Analyze the expression. const SCEV *createSCEV(Value *V); @@ -536,6 +539,15 @@ namespace llvm { const SCEV *FoundLHS, const SCEV *FoundRHS); + /// isImpliedCondOperandsViaRanges - Test whether the condition described by + /// Pred, LHS, and RHS is true whenever the condition described by Pred, + /// FoundLHS, and FoundRHS is true. Utility function used by + /// isImpliedCondOperands. + bool isImpliedCondOperandsViaRanges(ICmpInst::Predicate Pred, + const SCEV *LHS, const SCEV *RHS, + const SCEV *FoundLHS, + const SCEV *FoundRHS); + /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is /// in the header of its containing loop, we know the loop executes a /// constant number of times, and the PHI node is just a recurrence @@ -557,6 +569,15 @@ namespace llvm { /// pointer. bool checkValidity(const SCEV *S) const; + // Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal + // to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to + // proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if + // `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`). + // + template<typename ExtendOpTy> + bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step, + const Loop *L); + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); @@ -636,6 +657,15 @@ namespace llvm { SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end()); return getAddRecExpr(NewOp, L, Flags); } + /// \brief Returns an expression for a GEP + /// + /// \p PointeeType The type used as the basis for the pointer arithmetics + /// \p BaseExpr The expression for the pointer operand. + /// \p IndexExprs The expressions for the indices. + /// \p InBounds Whether the GEP is in bounds. + const SCEV *getGEPExpr(Type *PointeeType, const SCEV *BaseExpr, + const SmallVectorImpl<const SCEV *> &IndexExprs, + bool InBounds = false); const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands); const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS); @@ -830,11 +860,15 @@ namespace llvm { /// getUnsignedRange - Determine the unsigned range for a particular SCEV. /// - ConstantRange getUnsignedRange(const SCEV *S); + ConstantRange getUnsignedRange(const SCEV *S) { + return getRange(S, HINT_RANGE_UNSIGNED); + } /// getSignedRange - Determine the signed range for a particular SCEV. /// - ConstantRange getSignedRange(const SCEV *S); + ConstantRange getSignedRange(const SCEV *S) { + return getRange(S, HINT_RANGE_SIGNED); + } /// isKnownNegative - Test if the given expression is known to be negative. /// diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index b9bef970b5d3..8ec2078258d1 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -28,7 +28,7 @@ namespace llvm { /// all materialized values are safe to speculate. bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); - /// SCEVExpander - This class uses information about analyze scalars to + /// This class uses information about analyze scalars to /// rewrite expressions in canonical form. /// /// Clients should create an instance of this class when rewriting is needed, @@ -36,6 +36,7 @@ namespace llvm { /// memory. class SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { ScalarEvolution &SE; + const DataLayout &DL; // New instructions receive a name to identifies them with the current pass. const char* IVName; @@ -47,37 +48,36 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; - /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + /// A memoization of the "relevant" loop for a given SCEV. DenseMap<const SCEV *, const Loop *> RelevantLoops; - /// PostIncLoops - Addrecs referring to any of the given loops are expanded + /// \brief Addrecs referring to any of the given loops are expanded /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode /// returns the add instruction that adds one to the phi for {0,+,1}<L>, /// as opposed to a new phi starting at 1. This is only supported in /// non-canonical mode. PostIncLoopSet PostIncLoops; - /// IVIncInsertPos - When this is non-null, addrecs expanded in the - /// loop it indicates should be inserted with increments at - /// IVIncInsertPos. + /// \brief When this is non-null, addrecs expanded in the loop it indicates + /// should be inserted with increments at IVIncInsertPos. const Loop *IVIncInsertLoop; - /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop, - /// insert the IV increment at this position. + /// \brief When expanding addrecs in the IVIncInsertLoop loop, insert the IV + /// increment at this position. Instruction *IVIncInsertPos; - /// Phis that complete an IV chain. Reuse + /// \brief Phis that complete an IV chain. Reuse std::set<AssertingVH<PHINode> > ChainedPhis; - /// CanonicalMode - When true, expressions are expanded in "canonical" - /// form. In particular, addrecs are expanded as arithmetic based on - /// a canonical induction variable. When false, expression are expanded - /// in a more literal form. + /// \brief When true, expressions are expanded in "canonical" form. In + /// particular, addrecs are expanded as arithmetic based on a canonical + /// induction variable. When false, expression are expanded in a more + /// literal form. bool CanonicalMode; - /// When invoked from LSR, the expander is in "strength reduction" mode. The - /// only difference is that phi's are only reused if they are already in - /// "expanded" form. + /// \brief When invoked from LSR, the expander is in "strength reduction" + /// mode. The only difference is that phi's are only reused if they are + /// already in "expanded" form. bool LSRMode; typedef IRBuilder<true, TargetFolder> BuilderType; @@ -90,11 +90,12 @@ namespace llvm { friend struct SCEVVisitor<SCEVExpander, Value*>; public: - /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. - explicit SCEVExpander(ScalarEvolution &se, const char *name) - : SE(se), IVName(name), IVIncInsertLoop(nullptr), IVIncInsertPos(nullptr), - CanonicalMode(true), LSRMode(false), - Builder(se.getContext(), TargetFolder(se.DL)) { + /// \brief Construct a SCEVExpander in "canonical" mode. + explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL, + const char *name) + : SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr), + IVIncInsertPos(nullptr), CanonicalMode(true), LSRMode(false), + Builder(se.getContext(), TargetFolder(DL)) { #ifndef NDEBUG DebugType = ""; #endif @@ -104,7 +105,7 @@ namespace llvm { void setDebugType(const char* s) { DebugType = s; } #endif - /// clear - Erase the contents of the InsertedExpressions map so that users + /// \brief Erase the contents of the InsertedExpressions map so that users /// trying to expand the same expression into multiple BasicBlocks or /// different places within the same BasicBlock can do so. void clear() { @@ -114,31 +115,38 @@ namespace llvm { ChainedPhis.clear(); } - /// getOrInsertCanonicalInductionVariable - This method returns the - /// canonical induction variable of the specified type for the specified - /// loop (inserting one if there is none). A canonical induction variable - /// starts at zero and steps by one on each iteration. + /// \brief Return true for expressions that may incur non-trivial cost to + /// evaluate at runtime. + bool isHighCostExpansion(const SCEV *Expr, Loop *L) { + SmallPtrSet<const SCEV *, 8> Processed; + return isHighCostExpansionHelper(Expr, L, Processed); + } + + /// \brief This method returns the canonical induction variable of the + /// specified type for the specified loop (inserting one if there is none). + /// A canonical induction variable starts at zero and steps by one on each + /// iteration. PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty); - /// getIVIncOperand - Return the induction variable increment's IV operand. + /// \brief Return the induction variable increment's IV operand. Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos, bool allowScale); - /// hoistIVInc - Utility for hoisting an IV increment. + /// \brief Utility for hoisting an IV increment. bool hoistIVInc(Instruction *IncV, Instruction *InsertPos); - /// replaceCongruentIVs - replace congruent phis with their most canonical + /// \brief replace congruent phis with their most canonical /// representative. Return the number of phis eliminated. unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, SmallVectorImpl<WeakVH> &DeadInsts, const TargetTransformInfo *TTI = nullptr); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// specified block. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the specified + /// block. Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I); - /// setIVIncInsertPos - Set the current IV increment loop and position. + /// \brief Set the current IV increment loop and position. void setIVIncInsertPos(const Loop *L, Instruction *Pos) { assert(!CanonicalMode && "IV increment positions are not supported in CanonicalMode"); @@ -146,16 +154,15 @@ namespace llvm { IVIncInsertPos = Pos; } - /// setPostInc - Enable post-inc expansion for addrecs referring to the - /// given loops. Post-inc expansion is only supported in non-canonical - /// mode. + /// \brief Enable post-inc expansion for addrecs referring to the given + /// loops. Post-inc expansion is only supported in non-canonical mode. void setPostInc(const PostIncLoopSet &L) { assert(!CanonicalMode && "Post-inc expansion is not supported in CanonicalMode"); PostIncLoops = L; } - /// clearPostInc - Disable all post-inc expansion. + /// \brief Disable all post-inc expansion. void clearPostInc() { PostIncLoops.clear(); @@ -164,23 +171,22 @@ namespace llvm { InsertedPostIncValues.clear(); } - /// disableCanonicalMode - Disable the behavior of expanding expressions in - /// canonical form rather than in a more literal form. Non-canonical mode - /// is useful for late optimization passes. + /// \brief Disable the behavior of expanding expressions in canonical form + /// rather than in a more literal form. Non-canonical mode is useful for + /// late optimization passes. void disableCanonicalMode() { CanonicalMode = false; } void enableLSRMode() { LSRMode = true; } - /// clearInsertPoint - Clear the current insertion point. This is useful - /// if the instruction that had been serving as the insertion point may - /// have been deleted. + /// \brief Clear the current insertion point. This is useful if the + /// instruction that had been serving as the insertion point may have been + /// deleted. void clearInsertPoint() { Builder.ClearInsertionPoint(); } - /// isInsertedInstruction - Return true if the specified instruction was - /// inserted by the code rewriter. If so, the client should not modify the - /// instruction. + /// \brief Return true if the specified instruction was inserted by the code + /// rewriter. If so, the client should not modify the instruction. bool isInsertedInstruction(Instruction *I) const { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } @@ -190,24 +196,27 @@ namespace llvm { private: LLVMContext &getContext() const { return SE.getContext(); } - /// InsertBinop - Insert the specified binary operator, doing a small amount + /// \brief Recursive helper function for isHighCostExpansion. + bool isHighCostExpansionHelper(const SCEV *S, Loop *L, + SmallPtrSetImpl<const SCEV *> &Processed); + + /// \brief Insert the specified binary operator, doing a small amount /// of work to avoid inserting an obviously redundant operation. Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); - /// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP, - /// reusing an existing cast if a suitable one exists, moving an existing - /// cast if a suitable one exists but isn't in the right place, or - /// or creating a new one. + /// \brief Arrange for there to be a cast of V to Ty at IP, reusing an + /// existing cast if a suitable one exists, moving an existing cast if a + /// suitable one exists but isn't in the right place, or or creating a new + /// one. Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP); - /// InsertNoopCastOfTo - Insert a cast of V to the specified type, - /// which must be possible with a noop cast, doing what we can to - /// share the casts. + /// \brief Insert a cast of V to the specified type, which must be possible + /// with a noop cast, doing what we can to share the casts. Value *InsertNoopCastOfTo(Value *V, Type *Ty); - /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP + /// \brief Expand a SCEVAddExpr with a pointer type into a GEP /// instead of using ptrtoint+arithmetic+inttoptr. Value *expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, @@ -215,13 +224,13 @@ namespace llvm { Value *expand(const SCEV *S); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// SCEVExpander's current insertion point. If a type is specified, the - /// result will be expanded to have that type, with a cast if necessary. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the SCEVExpander's + /// current insertion point. If a type is specified, the result will be + /// expanded to have that type, with a cast if necessary. Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr); - /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + /// \brief Determine the most "relevant" loop for the given SCEV. const Loop *getRelevantLoop(const SCEV *); Value *visitConstant(const SCEVConstant *S) { diff --git a/include/llvm/Analysis/SparsePropagation.h b/include/llvm/Analysis/SparsePropagation.h index 65ff2f643192..9ccae5ff89b7 100644 --- a/include/llvm/Analysis/SparsePropagation.h +++ b/include/llvm/Analysis/SparsePropagation.h @@ -131,8 +131,8 @@ class SparseSolver { typedef std::pair<BasicBlock*,BasicBlock*> Edge; std::set<Edge> KnownFeasibleEdges; - SparseSolver(const SparseSolver&) LLVM_DELETED_FUNCTION; - void operator=(const SparseSolver&) LLVM_DELETED_FUNCTION; + SparseSolver(const SparseSolver&) = delete; + void operator=(const SparseSolver&) = delete; public: explicit SparseSolver(AbstractLatticeFunction *Lattice) : LatticeFunc(Lattice) {} diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index 587a7ef5410a..12bf9fe78a47 100644 --- a/include/llvm/Analysis/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -30,7 +30,7 @@ class DataLayout; /// TargetFolder - Create constants with target dependent folding. class TargetFolder { - const DataLayout *DL; + const DataLayout &DL; /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { @@ -41,7 +41,7 @@ class TargetFolder { } public: - explicit TargetFolder(const DataLayout *DL) : DL(DL) {} + explicit TargetFolder(const DataLayout &DL) : DL(DL) {} //===--------------------------------------------------------------------===// // Binary Operators @@ -130,34 +130,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx)); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetLibraryInfo.def b/include/llvm/Analysis/TargetLibraryInfo.def new file mode 100644 index 000000000000..1c1fdfef980d --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.def @@ -0,0 +1,1029 @@ +//===-- TargetLibraryInfo.def - Library information -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// This .def file will either fill in the enum definition or fill in the +// string representation array definition for TargetLibraryInfo. +// Which is defined depends on whether TLI_DEFINE_ENUM is defined or +// TLI_DEFINE_STRING is defined. Only one should be defined at a time. + +#if !(defined(TLI_DEFINE_ENUM) || defined(TLI_DEFINE_STRING)) +#error "Must define TLI_DEFINE_ENUM or TLI_DEFINE_STRING for TLI .def." +#elif defined(TLI_DEFINE_ENUM) && defined(TLI_DEFINE_STRING) +#error "Can only define one of TLI_DEFINE_ENUM or TLI_DEFINE_STRING at a time." +#else +// One of TLI_DEFINE_ENUM/STRING are defined. + +#if defined(TLI_DEFINE_ENUM) +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) enum_variant, +#define TLI_DEFINE_STRING_INTERNAL(string_repr) +#else +#define TLI_DEFINE_ENUM_INTERNAL(enum_variant) +#define TLI_DEFINE_STRING_INTERNAL(string_repr) string_repr, +#endif + +/// int _IO_getc(_IO_FILE * __fp); +TLI_DEFINE_ENUM_INTERNAL(under_IO_getc) +TLI_DEFINE_STRING_INTERNAL("_IO_getc") +/// int _IO_putc(int __c, _IO_FILE * __fp); +TLI_DEFINE_ENUM_INTERNAL(under_IO_putc) +TLI_DEFINE_STRING_INTERNAL("_IO_putc") +/// void operator delete[](void*); +TLI_DEFINE_ENUM_INTERNAL(ZdaPv) +TLI_DEFINE_STRING_INTERNAL("_ZdaPv") +/// void operator delete[](void*, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvRKSt9nothrow_t") +/// void operator delete[](void*, unsigned int); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvj) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvj") +/// void operator delete[](void*, unsigned long); +TLI_DEFINE_ENUM_INTERNAL(ZdaPvm) +TLI_DEFINE_STRING_INTERNAL("_ZdaPvm") +/// void operator delete(void*); +TLI_DEFINE_ENUM_INTERNAL(ZdlPv) +TLI_DEFINE_STRING_INTERNAL("_ZdlPv") +/// void operator delete(void*, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvRKSt9nothrow_t") +/// void operator delete(void*, unsigned int); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvj) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvj") +/// void operator delete(void*, unsigned long); +TLI_DEFINE_ENUM_INTERNAL(ZdlPvm) +TLI_DEFINE_STRING_INTERNAL("_ZdlPvm") +/// void *new[](unsigned int); +TLI_DEFINE_ENUM_INTERNAL(Znaj) +TLI_DEFINE_STRING_INTERNAL("_Znaj") +/// void *new[](unsigned int, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnajRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnajRKSt9nothrow_t") +/// void *new[](unsigned long); +TLI_DEFINE_ENUM_INTERNAL(Znam) +TLI_DEFINE_STRING_INTERNAL("_Znam") +/// void *new[](unsigned long, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnamRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnamRKSt9nothrow_t") +/// void *new(unsigned int); +TLI_DEFINE_ENUM_INTERNAL(Znwj) +TLI_DEFINE_STRING_INTERNAL("_Znwj") +/// void *new(unsigned int, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnwjRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwjRKSt9nothrow_t") +/// void *new(unsigned long); +TLI_DEFINE_ENUM_INTERNAL(Znwm) +TLI_DEFINE_STRING_INTERNAL("_Znwm") +/// void *new(unsigned long, nothrow); +TLI_DEFINE_ENUM_INTERNAL(ZnwmRKSt9nothrow_t) +TLI_DEFINE_STRING_INTERNAL("_ZnwmRKSt9nothrow_t") +/// double __cospi(double x); +TLI_DEFINE_ENUM_INTERNAL(cospi) +TLI_DEFINE_STRING_INTERNAL("__cospi") +/// float __cospif(float x); +TLI_DEFINE_ENUM_INTERNAL(cospif) +TLI_DEFINE_STRING_INTERNAL("__cospif") +/// int __cxa_atexit(void (*f)(void *), void *p, void *d); +TLI_DEFINE_ENUM_INTERNAL(cxa_atexit) +TLI_DEFINE_STRING_INTERNAL("__cxa_atexit") +/// void __cxa_guard_abort(guard_t *guard); +/// guard_t is int64_t in Itanium ABI or int32_t on ARM eabi. +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_abort) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_abort") +/// int __cxa_guard_acquire(guard_t *guard); +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_acquire) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_acquire") +/// void __cxa_guard_release(guard_t *guard); +TLI_DEFINE_ENUM_INTERNAL(cxa_guard_release) +TLI_DEFINE_STRING_INTERNAL("__cxa_guard_release") +/// int __isoc99_scanf (const char *format, ...) +TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_scanf) +TLI_DEFINE_STRING_INTERNAL("__isoc99_scanf") +/// int __isoc99_sscanf(const char *s, const char *format, ...) +TLI_DEFINE_ENUM_INTERNAL(dunder_isoc99_sscanf) +TLI_DEFINE_STRING_INTERNAL("__isoc99_sscanf") +/// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__memcpy_chk") +/// void *__memmove_chk(void *s1, const void *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memmove_chk) +TLI_DEFINE_STRING_INTERNAL("__memmove_chk") +/// void *__memset_chk(void *s, char v, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(memset_chk) +TLI_DEFINE_STRING_INTERNAL("__memset_chk") +/// double __sincospi_stret(double x); +TLI_DEFINE_ENUM_INTERNAL(sincospi_stret) +TLI_DEFINE_STRING_INTERNAL("__sincospi_stret") +/// float __sincospif_stret(float x); +TLI_DEFINE_ENUM_INTERNAL(sincospif_stret) +TLI_DEFINE_STRING_INTERNAL("__sincospif_stret") +/// double __sinpi(double x); +TLI_DEFINE_ENUM_INTERNAL(sinpi) +TLI_DEFINE_STRING_INTERNAL("__sinpi") +/// float __sinpif(float x); +TLI_DEFINE_ENUM_INTERNAL(sinpif) +TLI_DEFINE_STRING_INTERNAL("__sinpif") +/// double __sqrt_finite(double x); +TLI_DEFINE_ENUM_INTERNAL(sqrt_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrt_finite") +/// float __sqrt_finite(float x); +TLI_DEFINE_ENUM_INTERNAL(sqrtf_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrtf_finite") +/// long double __sqrt_finite(long double x); +TLI_DEFINE_ENUM_INTERNAL(sqrtl_finite) +TLI_DEFINE_STRING_INTERNAL("__sqrtl_finite") +/// char *__stpcpy_chk(char *s1, const char *s2, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(stpcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__stpcpy_chk") +/// char *__stpncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(stpncpy_chk) +TLI_DEFINE_STRING_INTERNAL("__stpncpy_chk") +/// char *__strcpy_chk(char *s1, const char *s2, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strcpy_chk) +TLI_DEFINE_STRING_INTERNAL("__strcpy_chk") +/// char * __strdup(const char *s); +TLI_DEFINE_ENUM_INTERNAL(dunder_strdup) +TLI_DEFINE_STRING_INTERNAL("__strdup") +/// char *__strncpy_chk(char *s1, const char *s2, size_t n, size_t s1size); +TLI_DEFINE_ENUM_INTERNAL(strncpy_chk) +TLI_DEFINE_STRING_INTERNAL("__strncpy_chk") +/// char *__strndup(const char *s, size_t n); +TLI_DEFINE_ENUM_INTERNAL(dunder_strndup) +TLI_DEFINE_STRING_INTERNAL("__strndup") +/// char * __strtok_r(char *s, const char *delim, char **save_ptr); +TLI_DEFINE_ENUM_INTERNAL(dunder_strtok_r) +TLI_DEFINE_STRING_INTERNAL("__strtok_r") +/// int abs(int j); +TLI_DEFINE_ENUM_INTERNAL(abs) +TLI_DEFINE_STRING_INTERNAL("abs") +/// int access(const char *path, int amode); +TLI_DEFINE_ENUM_INTERNAL(access) +TLI_DEFINE_STRING_INTERNAL("access") +/// double acos(double x); +TLI_DEFINE_ENUM_INTERNAL(acos) +TLI_DEFINE_STRING_INTERNAL("acos") +/// float acosf(float x); +TLI_DEFINE_ENUM_INTERNAL(acosf) +TLI_DEFINE_STRING_INTERNAL("acosf") +/// double acosh(double x); +TLI_DEFINE_ENUM_INTERNAL(acosh) +TLI_DEFINE_STRING_INTERNAL("acosh") +/// float acoshf(float x); +TLI_DEFINE_ENUM_INTERNAL(acoshf) +TLI_DEFINE_STRING_INTERNAL("acoshf") +/// long double acoshl(long double x); +TLI_DEFINE_ENUM_INTERNAL(acoshl) +TLI_DEFINE_STRING_INTERNAL("acoshl") +/// long double acosl(long double x); +TLI_DEFINE_ENUM_INTERNAL(acosl) +TLI_DEFINE_STRING_INTERNAL("acosl") +/// double asin(double x); +TLI_DEFINE_ENUM_INTERNAL(asin) +TLI_DEFINE_STRING_INTERNAL("asin") +/// float asinf(float x); +TLI_DEFINE_ENUM_INTERNAL(asinf) +TLI_DEFINE_STRING_INTERNAL("asinf") +/// double asinh(double x); +TLI_DEFINE_ENUM_INTERNAL(asinh) +TLI_DEFINE_STRING_INTERNAL("asinh") +/// float asinhf(float x); +TLI_DEFINE_ENUM_INTERNAL(asinhf) +TLI_DEFINE_STRING_INTERNAL("asinhf") +/// long double asinhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(asinhl) +TLI_DEFINE_STRING_INTERNAL("asinhl") +/// long double asinl(long double x); +TLI_DEFINE_ENUM_INTERNAL(asinl) +TLI_DEFINE_STRING_INTERNAL("asinl") +/// double atan(double x); +TLI_DEFINE_ENUM_INTERNAL(atan) +TLI_DEFINE_STRING_INTERNAL("atan") +/// double atan2(double y, double x); +TLI_DEFINE_ENUM_INTERNAL(atan2) +TLI_DEFINE_STRING_INTERNAL("atan2") +/// float atan2f(float y, float x); +TLI_DEFINE_ENUM_INTERNAL(atan2f) +TLI_DEFINE_STRING_INTERNAL("atan2f") +/// long double atan2l(long double y, long double x); +TLI_DEFINE_ENUM_INTERNAL(atan2l) +TLI_DEFINE_STRING_INTERNAL("atan2l") +/// float atanf(float x); +TLI_DEFINE_ENUM_INTERNAL(atanf) +TLI_DEFINE_STRING_INTERNAL("atanf") +/// double atanh(double x); +TLI_DEFINE_ENUM_INTERNAL(atanh) +TLI_DEFINE_STRING_INTERNAL("atanh") +/// float atanhf(float x); +TLI_DEFINE_ENUM_INTERNAL(atanhf) +TLI_DEFINE_STRING_INTERNAL("atanhf") +/// long double atanhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(atanhl) +TLI_DEFINE_STRING_INTERNAL("atanhl") +/// long double atanl(long double x); +TLI_DEFINE_ENUM_INTERNAL(atanl) +TLI_DEFINE_STRING_INTERNAL("atanl") +/// double atof(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atof) +TLI_DEFINE_STRING_INTERNAL("atof") +/// int atoi(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atoi) +TLI_DEFINE_STRING_INTERNAL("atoi") +/// long atol(const char *str); +TLI_DEFINE_ENUM_INTERNAL(atol) +TLI_DEFINE_STRING_INTERNAL("atol") +/// long long atoll(const char *nptr); +TLI_DEFINE_ENUM_INTERNAL(atoll) +TLI_DEFINE_STRING_INTERNAL("atoll") +/// int bcmp(const void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bcmp) +TLI_DEFINE_STRING_INTERNAL("bcmp") +/// void bcopy(const void *s1, void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bcopy) +TLI_DEFINE_STRING_INTERNAL("bcopy") +/// void bzero(void *s, size_t n); +TLI_DEFINE_ENUM_INTERNAL(bzero) +TLI_DEFINE_STRING_INTERNAL("bzero") +/// void *calloc(size_t count, size_t size); +TLI_DEFINE_ENUM_INTERNAL(calloc) +TLI_DEFINE_STRING_INTERNAL("calloc") +/// double cbrt(double x); +TLI_DEFINE_ENUM_INTERNAL(cbrt) +TLI_DEFINE_STRING_INTERNAL("cbrt") +/// float cbrtf(float x); +TLI_DEFINE_ENUM_INTERNAL(cbrtf) +TLI_DEFINE_STRING_INTERNAL("cbrtf") +/// long double cbrtl(long double x); +TLI_DEFINE_ENUM_INTERNAL(cbrtl) +TLI_DEFINE_STRING_INTERNAL("cbrtl") +/// double ceil(double x); +TLI_DEFINE_ENUM_INTERNAL(ceil) +TLI_DEFINE_STRING_INTERNAL("ceil") +/// float ceilf(float x); +TLI_DEFINE_ENUM_INTERNAL(ceilf) +TLI_DEFINE_STRING_INTERNAL("ceilf") +/// long double ceill(long double x); +TLI_DEFINE_ENUM_INTERNAL(ceill) +TLI_DEFINE_STRING_INTERNAL("ceill") +/// int chmod(const char *path, mode_t mode); +TLI_DEFINE_ENUM_INTERNAL(chmod) +TLI_DEFINE_STRING_INTERNAL("chmod") +/// int chown(const char *path, uid_t owner, gid_t group); +TLI_DEFINE_ENUM_INTERNAL(chown) +TLI_DEFINE_STRING_INTERNAL("chown") +/// void clearerr(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(clearerr) +TLI_DEFINE_STRING_INTERNAL("clearerr") +/// int closedir(DIR *dirp); +TLI_DEFINE_ENUM_INTERNAL(closedir) +TLI_DEFINE_STRING_INTERNAL("closedir") +/// double copysign(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(copysign) +TLI_DEFINE_STRING_INTERNAL("copysign") +/// float copysignf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(copysignf) +TLI_DEFINE_STRING_INTERNAL("copysignf") +/// long double copysignl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(copysignl) +TLI_DEFINE_STRING_INTERNAL("copysignl") +/// double cos(double x); +TLI_DEFINE_ENUM_INTERNAL(cos) +TLI_DEFINE_STRING_INTERNAL("cos") +/// float cosf(float x); +TLI_DEFINE_ENUM_INTERNAL(cosf) +TLI_DEFINE_STRING_INTERNAL("cosf") +/// double cosh(double x); +TLI_DEFINE_ENUM_INTERNAL(cosh) +TLI_DEFINE_STRING_INTERNAL("cosh") +/// float coshf(float x); +TLI_DEFINE_ENUM_INTERNAL(coshf) +TLI_DEFINE_STRING_INTERNAL("coshf") +/// long double coshl(long double x); +TLI_DEFINE_ENUM_INTERNAL(coshl) +TLI_DEFINE_STRING_INTERNAL("coshl") +/// long double cosl(long double x); +TLI_DEFINE_ENUM_INTERNAL(cosl) +TLI_DEFINE_STRING_INTERNAL("cosl") +/// char *ctermid(char *s); +TLI_DEFINE_ENUM_INTERNAL(ctermid) +TLI_DEFINE_STRING_INTERNAL("ctermid") +/// double exp(double x); +TLI_DEFINE_ENUM_INTERNAL(exp) +TLI_DEFINE_STRING_INTERNAL("exp") +/// double exp10(double x); +TLI_DEFINE_ENUM_INTERNAL(exp10) +TLI_DEFINE_STRING_INTERNAL("exp10") +/// float exp10f(float x); +TLI_DEFINE_ENUM_INTERNAL(exp10f) +TLI_DEFINE_STRING_INTERNAL("exp10f") +/// long double exp10l(long double x); +TLI_DEFINE_ENUM_INTERNAL(exp10l) +TLI_DEFINE_STRING_INTERNAL("exp10l") +/// double exp2(double x); +TLI_DEFINE_ENUM_INTERNAL(exp2) +TLI_DEFINE_STRING_INTERNAL("exp2") +/// float exp2f(float x); +TLI_DEFINE_ENUM_INTERNAL(exp2f) +TLI_DEFINE_STRING_INTERNAL("exp2f") +/// long double exp2l(long double x); +TLI_DEFINE_ENUM_INTERNAL(exp2l) +TLI_DEFINE_STRING_INTERNAL("exp2l") +/// float expf(float x); +TLI_DEFINE_ENUM_INTERNAL(expf) +TLI_DEFINE_STRING_INTERNAL("expf") +/// long double expl(long double x); +TLI_DEFINE_ENUM_INTERNAL(expl) +TLI_DEFINE_STRING_INTERNAL("expl") +/// double expm1(double x); +TLI_DEFINE_ENUM_INTERNAL(expm1) +TLI_DEFINE_STRING_INTERNAL("expm1") +/// float expm1f(float x); +TLI_DEFINE_ENUM_INTERNAL(expm1f) +TLI_DEFINE_STRING_INTERNAL("expm1f") +/// long double expm1l(long double x); +TLI_DEFINE_ENUM_INTERNAL(expm1l) +TLI_DEFINE_STRING_INTERNAL("expm1l") +/// double fabs(double x); +TLI_DEFINE_ENUM_INTERNAL(fabs) +TLI_DEFINE_STRING_INTERNAL("fabs") +/// float fabsf(float x); +TLI_DEFINE_ENUM_INTERNAL(fabsf) +TLI_DEFINE_STRING_INTERNAL("fabsf") +/// long double fabsl(long double x); +TLI_DEFINE_ENUM_INTERNAL(fabsl) +TLI_DEFINE_STRING_INTERNAL("fabsl") +/// int fclose(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fclose) +TLI_DEFINE_STRING_INTERNAL("fclose") +/// FILE *fdopen(int fildes, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(fdopen) +TLI_DEFINE_STRING_INTERNAL("fdopen") +/// int feof(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(feof) +TLI_DEFINE_STRING_INTERNAL("feof") +/// int ferror(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ferror) +TLI_DEFINE_STRING_INTERNAL("ferror") +/// int fflush(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fflush) +TLI_DEFINE_STRING_INTERNAL("fflush") +/// int ffs(int i); +TLI_DEFINE_ENUM_INTERNAL(ffs) +TLI_DEFINE_STRING_INTERNAL("ffs") +/// int ffsl(long int i); +TLI_DEFINE_ENUM_INTERNAL(ffsl) +TLI_DEFINE_STRING_INTERNAL("ffsl") +/// int ffsll(long long int i); +TLI_DEFINE_ENUM_INTERNAL(ffsll) +TLI_DEFINE_STRING_INTERNAL("ffsll") +/// int fgetc(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgetc) +TLI_DEFINE_STRING_INTERNAL("fgetc") +/// int fgetpos(FILE *stream, fpos_t *pos); +TLI_DEFINE_ENUM_INTERNAL(fgetpos) +TLI_DEFINE_STRING_INTERNAL("fgetpos") +/// char *fgets(char *s, int n, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fgets) +TLI_DEFINE_STRING_INTERNAL("fgets") +/// int fileno(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fileno) +TLI_DEFINE_STRING_INTERNAL("fileno") +/// int fiprintf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(fiprintf) +TLI_DEFINE_STRING_INTERNAL("fiprintf") +/// void flockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(flockfile) +TLI_DEFINE_STRING_INTERNAL("flockfile") +/// double floor(double x); +TLI_DEFINE_ENUM_INTERNAL(floor) +TLI_DEFINE_STRING_INTERNAL("floor") +/// float floorf(float x); +TLI_DEFINE_ENUM_INTERNAL(floorf) +TLI_DEFINE_STRING_INTERNAL("floorf") +/// long double floorl(long double x); +TLI_DEFINE_ENUM_INTERNAL(floorl) +TLI_DEFINE_STRING_INTERNAL("floorl") +/// double fmax(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmax) +TLI_DEFINE_STRING_INTERNAL("fmax") +/// float fmaxf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fmaxf) +TLI_DEFINE_STRING_INTERNAL("fmaxf") +/// long double fmaxl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fmaxl) +TLI_DEFINE_STRING_INTERNAL("fmaxl") +/// double fmin(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmin) +TLI_DEFINE_STRING_INTERNAL("fmin") +/// float fminf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fminf) +TLI_DEFINE_STRING_INTERNAL("fminf") +/// long double fminl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fminl) +TLI_DEFINE_STRING_INTERNAL("fminl") +/// double fmod(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(fmod) +TLI_DEFINE_STRING_INTERNAL("fmod") +/// float fmodf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(fmodf) +TLI_DEFINE_STRING_INTERNAL("fmodf") +/// long double fmodl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(fmodl) +TLI_DEFINE_STRING_INTERNAL("fmodl") +/// FILE *fopen(const char *filename, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(fopen) +TLI_DEFINE_STRING_INTERNAL("fopen") +/// FILE *fopen64(const char *filename, const char *opentype) +TLI_DEFINE_ENUM_INTERNAL(fopen64) +TLI_DEFINE_STRING_INTERNAL("fopen64") +/// int fprintf(FILE *stream, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(fprintf) +TLI_DEFINE_STRING_INTERNAL("fprintf") +/// int fputc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputc) +TLI_DEFINE_STRING_INTERNAL("fputc") +/// int fputs(const char *s, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fputs) +TLI_DEFINE_STRING_INTERNAL("fputs") +/// size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fread) +TLI_DEFINE_STRING_INTERNAL("fread") +/// void free(void *ptr); +TLI_DEFINE_ENUM_INTERNAL(free) +TLI_DEFINE_STRING_INTERNAL("free") +/// double frexp(double num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexp) +TLI_DEFINE_STRING_INTERNAL("frexp") +/// float frexpf(float num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexpf) +TLI_DEFINE_STRING_INTERNAL("frexpf") +/// long double frexpl(long double num, int *exp); +TLI_DEFINE_ENUM_INTERNAL(frexpl) +TLI_DEFINE_STRING_INTERNAL("frexpl") +/// int fscanf(FILE *stream, const char *format, ... ); +TLI_DEFINE_ENUM_INTERNAL(fscanf) +TLI_DEFINE_STRING_INTERNAL("fscanf") +/// int fseek(FILE *stream, long offset, int whence); +TLI_DEFINE_ENUM_INTERNAL(fseek) +TLI_DEFINE_STRING_INTERNAL("fseek") +/// int fseeko(FILE *stream, off_t offset, int whence); +TLI_DEFINE_ENUM_INTERNAL(fseeko) +TLI_DEFINE_STRING_INTERNAL("fseeko") +/// int fseeko64(FILE *stream, off64_t offset, int whence) +TLI_DEFINE_ENUM_INTERNAL(fseeko64) +TLI_DEFINE_STRING_INTERNAL("fseeko64") +/// int fsetpos(FILE *stream, const fpos_t *pos); +TLI_DEFINE_ENUM_INTERNAL(fsetpos) +TLI_DEFINE_STRING_INTERNAL("fsetpos") +/// int fstat(int fildes, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(fstat) +TLI_DEFINE_STRING_INTERNAL("fstat") +/// int fstat64(int filedes, struct stat64 *buf) +TLI_DEFINE_ENUM_INTERNAL(fstat64) +TLI_DEFINE_STRING_INTERNAL("fstat64") +/// int fstatvfs(int fildes, struct statvfs *buf); +TLI_DEFINE_ENUM_INTERNAL(fstatvfs) +TLI_DEFINE_STRING_INTERNAL("fstatvfs") +/// int fstatvfs64(int fildes, struct statvfs64 *buf); +TLI_DEFINE_ENUM_INTERNAL(fstatvfs64) +TLI_DEFINE_STRING_INTERNAL("fstatvfs64") +/// long ftell(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ftell) +TLI_DEFINE_STRING_INTERNAL("ftell") +/// off_t ftello(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ftello) +TLI_DEFINE_STRING_INTERNAL("ftello") +/// off64_t ftello64(FILE *stream) +TLI_DEFINE_ENUM_INTERNAL(ftello64) +TLI_DEFINE_STRING_INTERNAL("ftello64") +/// int ftrylockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(ftrylockfile) +TLI_DEFINE_STRING_INTERNAL("ftrylockfile") +/// void funlockfile(FILE *file); +TLI_DEFINE_ENUM_INTERNAL(funlockfile) +TLI_DEFINE_STRING_INTERNAL("funlockfile") +/// size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(fwrite) +TLI_DEFINE_STRING_INTERNAL("fwrite") +/// int getc(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(getc) +TLI_DEFINE_STRING_INTERNAL("getc") +/// int getc_unlocked(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(getc_unlocked) +TLI_DEFINE_STRING_INTERNAL("getc_unlocked") +/// int getchar(void); +TLI_DEFINE_ENUM_INTERNAL(getchar) +TLI_DEFINE_STRING_INTERNAL("getchar") +/// char *getenv(const char *name); +TLI_DEFINE_ENUM_INTERNAL(getenv) +TLI_DEFINE_STRING_INTERNAL("getenv") +/// int getitimer(int which, struct itimerval *value); +TLI_DEFINE_ENUM_INTERNAL(getitimer) +TLI_DEFINE_STRING_INTERNAL("getitimer") +/// int getlogin_r(char *name, size_t namesize); +TLI_DEFINE_ENUM_INTERNAL(getlogin_r) +TLI_DEFINE_STRING_INTERNAL("getlogin_r") +/// struct passwd *getpwnam(const char *name); +TLI_DEFINE_ENUM_INTERNAL(getpwnam) +TLI_DEFINE_STRING_INTERNAL("getpwnam") +/// char *gets(char *s); +TLI_DEFINE_ENUM_INTERNAL(gets) +TLI_DEFINE_STRING_INTERNAL("gets") +/// int gettimeofday(struct timeval *tp, void *tzp); +TLI_DEFINE_ENUM_INTERNAL(gettimeofday) +TLI_DEFINE_STRING_INTERNAL("gettimeofday") +/// uint32_t htonl(uint32_t hostlong); +TLI_DEFINE_ENUM_INTERNAL(htonl) +TLI_DEFINE_STRING_INTERNAL("htonl") +/// uint16_t htons(uint16_t hostshort); +TLI_DEFINE_ENUM_INTERNAL(htons) +TLI_DEFINE_STRING_INTERNAL("htons") +/// int iprintf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(iprintf) +TLI_DEFINE_STRING_INTERNAL("iprintf") +/// int isascii(int c); +TLI_DEFINE_ENUM_INTERNAL(isascii) +TLI_DEFINE_STRING_INTERNAL("isascii") +/// int isdigit(int c); +TLI_DEFINE_ENUM_INTERNAL(isdigit) +TLI_DEFINE_STRING_INTERNAL("isdigit") +/// long int labs(long int j); +TLI_DEFINE_ENUM_INTERNAL(labs) +TLI_DEFINE_STRING_INTERNAL("labs") +/// int lchown(const char *path, uid_t owner, gid_t group); +TLI_DEFINE_ENUM_INTERNAL(lchown) +TLI_DEFINE_STRING_INTERNAL("lchown") +/// double ldexp(double x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexp) +TLI_DEFINE_STRING_INTERNAL("ldexp") +/// float ldexpf(float x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexpf) +TLI_DEFINE_STRING_INTERNAL("ldexpf") +/// long double ldexpl(long double x, int n); +TLI_DEFINE_ENUM_INTERNAL(ldexpl) +TLI_DEFINE_STRING_INTERNAL("ldexpl") +/// long long int llabs(long long int j); +TLI_DEFINE_ENUM_INTERNAL(llabs) +TLI_DEFINE_STRING_INTERNAL("llabs") +/// double log(double x); +TLI_DEFINE_ENUM_INTERNAL(log) +TLI_DEFINE_STRING_INTERNAL("log") +/// double log10(double x); +TLI_DEFINE_ENUM_INTERNAL(log10) +TLI_DEFINE_STRING_INTERNAL("log10") +/// float log10f(float x); +TLI_DEFINE_ENUM_INTERNAL(log10f) +TLI_DEFINE_STRING_INTERNAL("log10f") +/// long double log10l(long double x); +TLI_DEFINE_ENUM_INTERNAL(log10l) +TLI_DEFINE_STRING_INTERNAL("log10l") +/// double log1p(double x); +TLI_DEFINE_ENUM_INTERNAL(log1p) +TLI_DEFINE_STRING_INTERNAL("log1p") +/// float log1pf(float x); +TLI_DEFINE_ENUM_INTERNAL(log1pf) +TLI_DEFINE_STRING_INTERNAL("log1pf") +/// long double log1pl(long double x); +TLI_DEFINE_ENUM_INTERNAL(log1pl) +TLI_DEFINE_STRING_INTERNAL("log1pl") +/// double log2(double x); +TLI_DEFINE_ENUM_INTERNAL(log2) +TLI_DEFINE_STRING_INTERNAL("log2") +/// float log2f(float x); +TLI_DEFINE_ENUM_INTERNAL(log2f) +TLI_DEFINE_STRING_INTERNAL("log2f") +/// double long double log2l(long double x); +TLI_DEFINE_ENUM_INTERNAL(log2l) +TLI_DEFINE_STRING_INTERNAL("log2l") +/// double logb(double x); +TLI_DEFINE_ENUM_INTERNAL(logb) +TLI_DEFINE_STRING_INTERNAL("logb") +/// float logbf(float x); +TLI_DEFINE_ENUM_INTERNAL(logbf) +TLI_DEFINE_STRING_INTERNAL("logbf") +/// long double logbl(long double x); +TLI_DEFINE_ENUM_INTERNAL(logbl) +TLI_DEFINE_STRING_INTERNAL("logbl") +/// float logf(float x); +TLI_DEFINE_ENUM_INTERNAL(logf) +TLI_DEFINE_STRING_INTERNAL("logf") +/// long double logl(long double x); +TLI_DEFINE_ENUM_INTERNAL(logl) +TLI_DEFINE_STRING_INTERNAL("logl") +/// int lstat(const char *path, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(lstat) +TLI_DEFINE_STRING_INTERNAL("lstat") +/// int lstat64(const char *path, struct stat64 *buf); +TLI_DEFINE_ENUM_INTERNAL(lstat64) +TLI_DEFINE_STRING_INTERNAL("lstat64") +/// void *malloc(size_t size); +TLI_DEFINE_ENUM_INTERNAL(malloc) +TLI_DEFINE_STRING_INTERNAL("malloc") +/// void *memalign(size_t boundary, size_t size); +TLI_DEFINE_ENUM_INTERNAL(memalign) +TLI_DEFINE_STRING_INTERNAL("memalign") +/// void *memccpy(void *s1, const void *s2, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memccpy) +TLI_DEFINE_STRING_INTERNAL("memccpy") +/// void *memchr(const void *s, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memchr) +TLI_DEFINE_STRING_INTERNAL("memchr") +/// int memcmp(const void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memcmp) +TLI_DEFINE_STRING_INTERNAL("memcmp") +/// void *memcpy(void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memcpy) +TLI_DEFINE_STRING_INTERNAL("memcpy") +/// void *memmove(void *s1, const void *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memmove) +TLI_DEFINE_STRING_INTERNAL("memmove") +// void *memrchr(const void *s, int c, size_t n); +TLI_DEFINE_ENUM_INTERNAL(memrchr) +TLI_DEFINE_STRING_INTERNAL("memrchr") +/// void *memset(void *b, int c, size_t len); +TLI_DEFINE_ENUM_INTERNAL(memset) +TLI_DEFINE_STRING_INTERNAL("memset") +/// void memset_pattern16(void *b, const void *pattern16, size_t len); +TLI_DEFINE_ENUM_INTERNAL(memset_pattern16) +TLI_DEFINE_STRING_INTERNAL("memset_pattern16") +/// int mkdir(const char *path, mode_t mode); +TLI_DEFINE_ENUM_INTERNAL(mkdir) +TLI_DEFINE_STRING_INTERNAL("mkdir") +/// time_t mktime(struct tm *timeptr); +TLI_DEFINE_ENUM_INTERNAL(mktime) +TLI_DEFINE_STRING_INTERNAL("mktime") +/// double modf(double x, double *iptr); +TLI_DEFINE_ENUM_INTERNAL(modf) +TLI_DEFINE_STRING_INTERNAL("modf") +/// float modff(float, float *iptr); +TLI_DEFINE_ENUM_INTERNAL(modff) +TLI_DEFINE_STRING_INTERNAL("modff") +/// long double modfl(long double value, long double *iptr); +TLI_DEFINE_ENUM_INTERNAL(modfl) +TLI_DEFINE_STRING_INTERNAL("modfl") +/// double nearbyint(double x); +TLI_DEFINE_ENUM_INTERNAL(nearbyint) +TLI_DEFINE_STRING_INTERNAL("nearbyint") +/// float nearbyintf(float x); +TLI_DEFINE_ENUM_INTERNAL(nearbyintf) +TLI_DEFINE_STRING_INTERNAL("nearbyintf") +/// long double nearbyintl(long double x); +TLI_DEFINE_ENUM_INTERNAL(nearbyintl) +TLI_DEFINE_STRING_INTERNAL("nearbyintl") +/// uint32_t ntohl(uint32_t netlong); +TLI_DEFINE_ENUM_INTERNAL(ntohl) +TLI_DEFINE_STRING_INTERNAL("ntohl") +/// uint16_t ntohs(uint16_t netshort); +TLI_DEFINE_ENUM_INTERNAL(ntohs) +TLI_DEFINE_STRING_INTERNAL("ntohs") +/// int open(const char *path, int oflag, ... ); +TLI_DEFINE_ENUM_INTERNAL(open) +TLI_DEFINE_STRING_INTERNAL("open") +/// int open64(const char *filename, int flags[, mode_t mode]) +TLI_DEFINE_ENUM_INTERNAL(open64) +TLI_DEFINE_STRING_INTERNAL("open64") +/// DIR *opendir(const char *dirname); +TLI_DEFINE_ENUM_INTERNAL(opendir) +TLI_DEFINE_STRING_INTERNAL("opendir") +/// int pclose(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(pclose) +TLI_DEFINE_STRING_INTERNAL("pclose") +/// void perror(const char *s); +TLI_DEFINE_ENUM_INTERNAL(perror) +TLI_DEFINE_STRING_INTERNAL("perror") +/// FILE *popen(const char *command, const char *mode); +TLI_DEFINE_ENUM_INTERNAL(popen) +TLI_DEFINE_STRING_INTERNAL("popen") +/// int posix_memalign(void **memptr, size_t alignment, size_t size); +TLI_DEFINE_ENUM_INTERNAL(posix_memalign) +TLI_DEFINE_STRING_INTERNAL("posix_memalign") +/// double pow(double x, double y); +TLI_DEFINE_ENUM_INTERNAL(pow) +TLI_DEFINE_STRING_INTERNAL("pow") +/// float powf(float x, float y); +TLI_DEFINE_ENUM_INTERNAL(powf) +TLI_DEFINE_STRING_INTERNAL("powf") +/// long double powl(long double x, long double y); +TLI_DEFINE_ENUM_INTERNAL(powl) +TLI_DEFINE_STRING_INTERNAL("powl") +/// ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); +TLI_DEFINE_ENUM_INTERNAL(pread) +TLI_DEFINE_STRING_INTERNAL("pread") +/// int printf(const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(printf) +TLI_DEFINE_STRING_INTERNAL("printf") +/// int putc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(putc) +TLI_DEFINE_STRING_INTERNAL("putc") +/// int putchar(int c); +TLI_DEFINE_ENUM_INTERNAL(putchar) +TLI_DEFINE_STRING_INTERNAL("putchar") +/// int puts(const char *s); +TLI_DEFINE_ENUM_INTERNAL(puts) +TLI_DEFINE_STRING_INTERNAL("puts") +/// ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset); +TLI_DEFINE_ENUM_INTERNAL(pwrite) +TLI_DEFINE_STRING_INTERNAL("pwrite") +/// void qsort(void *base, size_t nel, size_t width, +/// int (*compar)(const void *, const void *)); +TLI_DEFINE_ENUM_INTERNAL(qsort) +TLI_DEFINE_STRING_INTERNAL("qsort") +/// ssize_t read(int fildes, void *buf, size_t nbyte); +TLI_DEFINE_ENUM_INTERNAL(read) +TLI_DEFINE_STRING_INTERNAL("read") +/// ssize_t readlink(const char *path, char *buf, size_t bufsize); +TLI_DEFINE_ENUM_INTERNAL(readlink) +TLI_DEFINE_STRING_INTERNAL("readlink") +/// void *realloc(void *ptr, size_t size); +TLI_DEFINE_ENUM_INTERNAL(realloc) +TLI_DEFINE_STRING_INTERNAL("realloc") +/// void *reallocf(void *ptr, size_t size); +TLI_DEFINE_ENUM_INTERNAL(reallocf) +TLI_DEFINE_STRING_INTERNAL("reallocf") +/// char *realpath(const char *file_name, char *resolved_name); +TLI_DEFINE_ENUM_INTERNAL(realpath) +TLI_DEFINE_STRING_INTERNAL("realpath") +/// int remove(const char *path); +TLI_DEFINE_ENUM_INTERNAL(remove) +TLI_DEFINE_STRING_INTERNAL("remove") +/// int rename(const char *old, const char *new); +TLI_DEFINE_ENUM_INTERNAL(rename) +TLI_DEFINE_STRING_INTERNAL("rename") +/// void rewind(FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(rewind) +TLI_DEFINE_STRING_INTERNAL("rewind") +/// double rint(double x); +TLI_DEFINE_ENUM_INTERNAL(rint) +TLI_DEFINE_STRING_INTERNAL("rint") +/// float rintf(float x); +TLI_DEFINE_ENUM_INTERNAL(rintf) +TLI_DEFINE_STRING_INTERNAL("rintf") +/// long double rintl(long double x); +TLI_DEFINE_ENUM_INTERNAL(rintl) +TLI_DEFINE_STRING_INTERNAL("rintl") +/// int rmdir(const char *path); +TLI_DEFINE_ENUM_INTERNAL(rmdir) +TLI_DEFINE_STRING_INTERNAL("rmdir") +/// double round(double x); +TLI_DEFINE_ENUM_INTERNAL(round) +TLI_DEFINE_STRING_INTERNAL("round") +/// float roundf(float x); +TLI_DEFINE_ENUM_INTERNAL(roundf) +TLI_DEFINE_STRING_INTERNAL("roundf") +/// long double roundl(long double x); +TLI_DEFINE_ENUM_INTERNAL(roundl) +TLI_DEFINE_STRING_INTERNAL("roundl") +/// int scanf(const char *restrict format, ... ); +TLI_DEFINE_ENUM_INTERNAL(scanf) +TLI_DEFINE_STRING_INTERNAL("scanf") +/// void setbuf(FILE *stream, char *buf); +TLI_DEFINE_ENUM_INTERNAL(setbuf) +TLI_DEFINE_STRING_INTERNAL("setbuf") +/// int setitimer(int which, const struct itimerval *value, +/// struct itimerval *ovalue); +TLI_DEFINE_ENUM_INTERNAL(setitimer) +TLI_DEFINE_STRING_INTERNAL("setitimer") +/// int setvbuf(FILE *stream, char *buf, int type, size_t size); +TLI_DEFINE_ENUM_INTERNAL(setvbuf) +TLI_DEFINE_STRING_INTERNAL("setvbuf") +/// double sin(double x); +TLI_DEFINE_ENUM_INTERNAL(sin) +TLI_DEFINE_STRING_INTERNAL("sin") +/// float sinf(float x); +TLI_DEFINE_ENUM_INTERNAL(sinf) +TLI_DEFINE_STRING_INTERNAL("sinf") +/// double sinh(double x); +TLI_DEFINE_ENUM_INTERNAL(sinh) +TLI_DEFINE_STRING_INTERNAL("sinh") +/// float sinhf(float x); +TLI_DEFINE_ENUM_INTERNAL(sinhf) +TLI_DEFINE_STRING_INTERNAL("sinhf") +/// long double sinhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sinhl) +TLI_DEFINE_STRING_INTERNAL("sinhl") +/// long double sinl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sinl) +TLI_DEFINE_STRING_INTERNAL("sinl") +/// int siprintf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(siprintf) +TLI_DEFINE_STRING_INTERNAL("siprintf") +/// int snprintf(char *s, size_t n, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(snprintf) +TLI_DEFINE_STRING_INTERNAL("snprintf") +/// int sprintf(char *str, const char *format, ...); +TLI_DEFINE_ENUM_INTERNAL(sprintf) +TLI_DEFINE_STRING_INTERNAL("sprintf") +/// double sqrt(double x); +TLI_DEFINE_ENUM_INTERNAL(sqrt) +TLI_DEFINE_STRING_INTERNAL("sqrt") +/// float sqrtf(float x); +TLI_DEFINE_ENUM_INTERNAL(sqrtf) +TLI_DEFINE_STRING_INTERNAL("sqrtf") +/// long double sqrtl(long double x); +TLI_DEFINE_ENUM_INTERNAL(sqrtl) +TLI_DEFINE_STRING_INTERNAL("sqrtl") +/// int sscanf(const char *s, const char *format, ... ); +TLI_DEFINE_ENUM_INTERNAL(sscanf) +TLI_DEFINE_STRING_INTERNAL("sscanf") +/// int stat(const char *path, struct stat *buf); +TLI_DEFINE_ENUM_INTERNAL(stat) +TLI_DEFINE_STRING_INTERNAL("stat") +/// int stat64(const char *path, struct stat64 *buf); +TLI_DEFINE_ENUM_INTERNAL(stat64) +TLI_DEFINE_STRING_INTERNAL("stat64") +/// int statvfs(const char *path, struct statvfs *buf); +TLI_DEFINE_ENUM_INTERNAL(statvfs) +TLI_DEFINE_STRING_INTERNAL("statvfs") +/// int statvfs64(const char *path, struct statvfs64 *buf) +TLI_DEFINE_ENUM_INTERNAL(statvfs64) +TLI_DEFINE_STRING_INTERNAL("statvfs64") +/// char *stpcpy(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(stpcpy) +TLI_DEFINE_STRING_INTERNAL("stpcpy") +/// char *stpncpy(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(stpncpy) +TLI_DEFINE_STRING_INTERNAL("stpncpy") +/// int strcasecmp(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcasecmp) +TLI_DEFINE_STRING_INTERNAL("strcasecmp") +/// char *strcat(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcat) +TLI_DEFINE_STRING_INTERNAL("strcat") +/// char *strchr(const char *s, int c); +TLI_DEFINE_ENUM_INTERNAL(strchr) +TLI_DEFINE_STRING_INTERNAL("strchr") +/// int strcmp(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcmp) +TLI_DEFINE_STRING_INTERNAL("strcmp") +/// int strcoll(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcoll) +TLI_DEFINE_STRING_INTERNAL("strcoll") +/// char *strcpy(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcpy) +TLI_DEFINE_STRING_INTERNAL("strcpy") +/// size_t strcspn(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strcspn) +TLI_DEFINE_STRING_INTERNAL("strcspn") +/// char *strdup(const char *s1); +TLI_DEFINE_ENUM_INTERNAL(strdup) +TLI_DEFINE_STRING_INTERNAL("strdup") +/// size_t strlen(const char *s); +TLI_DEFINE_ENUM_INTERNAL(strlen) +TLI_DEFINE_STRING_INTERNAL("strlen") +/// int strncasecmp(const char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncasecmp) +TLI_DEFINE_STRING_INTERNAL("strncasecmp") +/// char *strncat(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncat) +TLI_DEFINE_STRING_INTERNAL("strncat") +/// int strncmp(const char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncmp) +TLI_DEFINE_STRING_INTERNAL("strncmp") +/// char *strncpy(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strncpy) +TLI_DEFINE_STRING_INTERNAL("strncpy") +/// char *strndup(const char *s1, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strndup) +TLI_DEFINE_STRING_INTERNAL("strndup") +/// size_t strnlen(const char *s, size_t maxlen); +TLI_DEFINE_ENUM_INTERNAL(strnlen) +TLI_DEFINE_STRING_INTERNAL("strnlen") +/// char *strpbrk(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strpbrk) +TLI_DEFINE_STRING_INTERNAL("strpbrk") +/// char *strrchr(const char *s, int c); +TLI_DEFINE_ENUM_INTERNAL(strrchr) +TLI_DEFINE_STRING_INTERNAL("strrchr") +/// size_t strspn(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strspn) +TLI_DEFINE_STRING_INTERNAL("strspn") +/// char *strstr(const char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strstr) +TLI_DEFINE_STRING_INTERNAL("strstr") +/// double strtod(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtod) +TLI_DEFINE_STRING_INTERNAL("strtod") +/// float strtof(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtof) +TLI_DEFINE_STRING_INTERNAL("strtof") +// char *strtok(char *s1, const char *s2); +TLI_DEFINE_ENUM_INTERNAL(strtok) +TLI_DEFINE_STRING_INTERNAL("strtok") +// char *strtok_r(char *s, const char *sep, char **lasts); +TLI_DEFINE_ENUM_INTERNAL(strtok_r) +TLI_DEFINE_STRING_INTERNAL("strtok_r") +/// long int strtol(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtol) +TLI_DEFINE_STRING_INTERNAL("strtol") +/// long double strtold(const char *nptr, char **endptr); +TLI_DEFINE_ENUM_INTERNAL(strtold) +TLI_DEFINE_STRING_INTERNAL("strtold") +/// long long int strtoll(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoll) +TLI_DEFINE_STRING_INTERNAL("strtoll") +/// unsigned long int strtoul(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoul) +TLI_DEFINE_STRING_INTERNAL("strtoul") +/// unsigned long long int strtoull(const char *nptr, char **endptr, int base); +TLI_DEFINE_ENUM_INTERNAL(strtoull) +TLI_DEFINE_STRING_INTERNAL("strtoull") +/// size_t strxfrm(char *s1, const char *s2, size_t n); +TLI_DEFINE_ENUM_INTERNAL(strxfrm) +TLI_DEFINE_STRING_INTERNAL("strxfrm") +/// int system(const char *command); +TLI_DEFINE_ENUM_INTERNAL(system) +TLI_DEFINE_STRING_INTERNAL("system") +/// double tan(double x); +TLI_DEFINE_ENUM_INTERNAL(tan) +TLI_DEFINE_STRING_INTERNAL("tan") +/// float tanf(float x); +TLI_DEFINE_ENUM_INTERNAL(tanf) +TLI_DEFINE_STRING_INTERNAL("tanf") +/// double tanh(double x); +TLI_DEFINE_ENUM_INTERNAL(tanh) +TLI_DEFINE_STRING_INTERNAL("tanh") +/// float tanhf(float x); +TLI_DEFINE_ENUM_INTERNAL(tanhf) +TLI_DEFINE_STRING_INTERNAL("tanhf") +/// long double tanhl(long double x); +TLI_DEFINE_ENUM_INTERNAL(tanhl) +TLI_DEFINE_STRING_INTERNAL("tanhl") +/// long double tanl(long double x); +TLI_DEFINE_ENUM_INTERNAL(tanl) +TLI_DEFINE_STRING_INTERNAL("tanl") +/// clock_t times(struct tms *buffer); +TLI_DEFINE_ENUM_INTERNAL(times) +TLI_DEFINE_STRING_INTERNAL("times") +/// FILE *tmpfile(void); +TLI_DEFINE_ENUM_INTERNAL(tmpfile) +TLI_DEFINE_STRING_INTERNAL("tmpfile") +/// FILE *tmpfile64(void) +TLI_DEFINE_ENUM_INTERNAL(tmpfile64) +TLI_DEFINE_STRING_INTERNAL("tmpfile64") +/// int toascii(int c); +TLI_DEFINE_ENUM_INTERNAL(toascii) +TLI_DEFINE_STRING_INTERNAL("toascii") +/// double trunc(double x); +TLI_DEFINE_ENUM_INTERNAL(trunc) +TLI_DEFINE_STRING_INTERNAL("trunc") +/// float truncf(float x); +TLI_DEFINE_ENUM_INTERNAL(truncf) +TLI_DEFINE_STRING_INTERNAL("truncf") +/// long double truncl(long double x); +TLI_DEFINE_ENUM_INTERNAL(truncl) +TLI_DEFINE_STRING_INTERNAL("truncl") +/// int uname(struct utsname *name); +TLI_DEFINE_ENUM_INTERNAL(uname) +TLI_DEFINE_STRING_INTERNAL("uname") +/// int ungetc(int c, FILE *stream); +TLI_DEFINE_ENUM_INTERNAL(ungetc) +TLI_DEFINE_STRING_INTERNAL("ungetc") +/// int unlink(const char *path); +TLI_DEFINE_ENUM_INTERNAL(unlink) +TLI_DEFINE_STRING_INTERNAL("unlink") +/// int unsetenv(const char *name); +TLI_DEFINE_ENUM_INTERNAL(unsetenv) +TLI_DEFINE_STRING_INTERNAL("unsetenv") +/// int utime(const char *path, const struct utimbuf *times); +TLI_DEFINE_ENUM_INTERNAL(utime) +TLI_DEFINE_STRING_INTERNAL("utime") +/// int utimes(const char *path, const struct timeval times[2]); +TLI_DEFINE_ENUM_INTERNAL(utimes) +TLI_DEFINE_STRING_INTERNAL("utimes") +/// void *valloc(size_t size); +TLI_DEFINE_ENUM_INTERNAL(valloc) +TLI_DEFINE_STRING_INTERNAL("valloc") +/// int vfprintf(FILE *stream, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vfprintf) +TLI_DEFINE_STRING_INTERNAL("vfprintf") +/// int vfscanf(FILE *stream, const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vfscanf) +TLI_DEFINE_STRING_INTERNAL("vfscanf") +/// int vprintf(const char *restrict format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vprintf) +TLI_DEFINE_STRING_INTERNAL("vprintf") +/// int vscanf(const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vscanf) +TLI_DEFINE_STRING_INTERNAL("vscanf") +/// int vsnprintf(char *s, size_t n, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsnprintf) +TLI_DEFINE_STRING_INTERNAL("vsnprintf") +/// int vsprintf(char *s, const char *format, va_list ap); +TLI_DEFINE_ENUM_INTERNAL(vsprintf) +TLI_DEFINE_STRING_INTERNAL("vsprintf") +/// int vsscanf(const char *s, const char *format, va_list arg); +TLI_DEFINE_ENUM_INTERNAL(vsscanf) +TLI_DEFINE_STRING_INTERNAL("vsscanf") +/// ssize_t write(int fildes, const void *buf, size_t nbyte); +TLI_DEFINE_ENUM_INTERNAL(write) +TLI_DEFINE_STRING_INTERNAL("write") + +#undef TLI_DEFINE_ENUM_INTERNAL +#undef TLI_DEFINE_STRING_INTERNAL +#endif // One of TLI_DEFINE_ENUM/STRING are defined. + +#undef TLI_DEFINE_ENUM +#undef TLI_DEFINE_STRING diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h new file mode 100644 index 000000000000..e0a1ee378274 --- /dev/null +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -0,0 +1,328 @@ +//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H +#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +namespace llvm { +/// VecDesc - Describes a possible vectorization of a function. +/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized +/// by a factor 'VectorizationFactor'. +struct VecDesc { + const char *ScalarFnName; + const char *VectorFnName; + unsigned VectorizationFactor; +}; +class PreservedAnalyses; + + namespace LibFunc { + enum Func { +#define TLI_DEFINE_ENUM +#include "llvm/Analysis/TargetLibraryInfo.def" + + NumLibFuncs + }; + } + +/// \brief Implementation of the target library information. +/// +/// This class constructs tables that hold the target library information and +/// make it available. However, it is somewhat expensive to compute and only +/// depends on the triple. So users typicaly interact with the \c +/// TargetLibraryInfo wrapper below. +class TargetLibraryInfoImpl { + friend class TargetLibraryInfo; + + unsigned char AvailableArray[(LibFunc::NumLibFuncs+3)/4]; + llvm::DenseMap<unsigned, std::string> CustomNames; + static const char *const StandardNames[LibFunc::NumLibFuncs]; + + enum AvailabilityState { + StandardName = 3, // (memset to all ones) + CustomName = 1, + Unavailable = 0 // (memset to all zeros) + }; + void setState(LibFunc::Func F, AvailabilityState State) { + AvailableArray[F/4] &= ~(3 << 2*(F&3)); + AvailableArray[F/4] |= State << 2*(F&3); + } + AvailabilityState getState(LibFunc::Func F) const { + return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3); + } + + /// Vectorization descriptors - sorted by ScalarFnName. + std::vector<VecDesc> VectorDescs; + /// Scalarization descriptors - same content as VectorDescs but sorted based + /// on VectorFnName rather than ScalarFnName. + std::vector<VecDesc> ScalarDescs; + +public: + /// \brief List of known vector-functions libraries. + /// + /// The vector-functions library defines, which functions are vectorizable + /// and with which factor. The library can be specified by either frontend, + /// or a commandline option, and then used by + /// addVectorizableFunctionsFromVecLib for filling up the tables of + /// vectorizable functions. + enum VectorLibrary { + NoLibrary, // Don't use any vector library. + Accelerate // Use Accelerate framework. + }; + + TargetLibraryInfoImpl(); + explicit TargetLibraryInfoImpl(const Triple &T); + + // Provide value semantics. + TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI); + TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI); + TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI); + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const; + + /// \brief Forces a function to be marked as unavailable. + void setUnavailable(LibFunc::Func F) { + setState(F, Unavailable); + } + + /// \brief Forces a function to be marked as available. + void setAvailable(LibFunc::Func F) { + setState(F, StandardName); + } + + /// \brief Forces a function to be marked as available and provide an + /// alternate name that must be used. + void setAvailableWithName(LibFunc::Func F, StringRef Name) { + if (StandardNames[F] != Name) { + setState(F, CustomName); + CustomNames[F] = Name; + assert(CustomNames.find(F) != CustomNames.end()); + } else { + setState(F, StandardName); + } + } + + /// \brief Disables all builtins. + /// + /// This can be used for options like -fno-builtin. + void disableAllFunctions(); + + /// addVectorizableFunctions - Add a set of scalar -> vector mappings, + /// queryable via getVectorizedFunction and getScalarizedFunction. + void addVectorizableFunctions(ArrayRef<VecDesc> Fns); + + /// Calls addVectorizableFunctions with a known preset of functions for the + /// given vector library. + void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib); + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with vectorization factor VF. + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return !getVectorizedFunction(F, VF).empty(); + } + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with any vectorization factor. + bool isFunctionVectorizable(StringRef F) const; + + /// getVectorizedFunction - Return the name of the equivalent of + /// F, vectorized with factor VF. If no such mapping exists, + /// return the empty string. + StringRef getVectorizedFunction(StringRef F, unsigned VF) const; + + /// isFunctionScalarizable - Return true if the function F has a + /// scalar equivalent, and set VF to be the vectorization factor. + bool isFunctionScalarizable(StringRef F, unsigned &VF) const { + return !getScalarizedFunction(F, VF).empty(); + } + + /// getScalarizedFunction - Return the name of the equivalent of + /// F, scalarized. If no such mapping exists, return the empty string. + /// + /// Set VF to the vectorization factor. + StringRef getScalarizedFunction(StringRef F, unsigned &VF) const; +}; + +/// \brief Provides information about what library functions are available for +/// the current target. +/// +/// This both allows optimizations to handle them specially and frontends to +/// disable such optimizations through -fno-builtin etc. +class TargetLibraryInfo { + friend class TargetLibraryAnalysis; + friend class TargetLibraryInfoWrapperPass; + + const TargetLibraryInfoImpl *Impl; + +public: + explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {} + + // Provide value semantics. + TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { + Impl = TLI.Impl; + return *this; + } + TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { + Impl = TLI.Impl; + return *this; + } + + /// \brief Searches for a particular function name. + /// + /// If it is one of the known library functions, return true and set F to the + /// corresponding value. + bool getLibFunc(StringRef funcName, LibFunc::Func &F) const { + return Impl->getLibFunc(funcName, F); + } + + /// \brief Tests whether a library function is available. + bool has(LibFunc::Func F) const { + return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + } + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return Impl->isFunctionVectorizable(F, VF); + }; + bool isFunctionVectorizable(StringRef F) const { + return Impl->isFunctionVectorizable(F); + }; + StringRef getVectorizedFunction(StringRef F, unsigned VF) const { + return Impl->getVectorizedFunction(F, VF); + }; + + /// \brief Tests if the function is both available and a candidate for + /// optimized code generation. + bool hasOptimizedCodeGen(LibFunc::Func F) const { + if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + return false; + switch (F) { + default: break; + case LibFunc::copysign: case LibFunc::copysignf: case LibFunc::copysignl: + case LibFunc::fabs: case LibFunc::fabsf: case LibFunc::fabsl: + case LibFunc::sin: case LibFunc::sinf: case LibFunc::sinl: + case LibFunc::cos: case LibFunc::cosf: case LibFunc::cosl: + case LibFunc::sqrt: case LibFunc::sqrtf: case LibFunc::sqrtl: + case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite: + case LibFunc::sqrtl_finite: + case LibFunc::fmax: case LibFunc::fmaxf: case LibFunc::fmaxl: + case LibFunc::fmin: case LibFunc::fminf: case LibFunc::fminl: + case LibFunc::floor: case LibFunc::floorf: case LibFunc::floorl: + case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl: + case LibFunc::ceil: case LibFunc::ceilf: case LibFunc::ceill: + case LibFunc::rint: case LibFunc::rintf: case LibFunc::rintl: + case LibFunc::round: case LibFunc::roundf: case LibFunc::roundl: + case LibFunc::trunc: case LibFunc::truncf: case LibFunc::truncl: + case LibFunc::log2: case LibFunc::log2f: case LibFunc::log2l: + case LibFunc::exp2: case LibFunc::exp2f: case LibFunc::exp2l: + case LibFunc::memcmp: case LibFunc::strcmp: case LibFunc::strcpy: + case LibFunc::stpcpy: case LibFunc::strlen: case LibFunc::strnlen: + case LibFunc::memchr: + return true; + } + return false; + } + + StringRef getName(LibFunc::Func F) const { + auto State = Impl->getState(F); + if (State == TargetLibraryInfoImpl::Unavailable) + return StringRef(); + if (State == TargetLibraryInfoImpl::StandardName) + return Impl->StandardNames[F]; + assert(State == TargetLibraryInfoImpl::CustomName); + return Impl->CustomNames.find(F)->second; + } + + /// \brief Handle invalidation from the pass manager. + /// + /// If we try to invalidate this info, just return false. It cannot become + /// invalid even if the module changes. + bool invalidate(Module &, const PreservedAnalyses &) { return false; } +}; + +/// \brief Analysis pass providing the \c TargetLibraryInfo. +/// +/// Note that this pass's result cannot be invalidated, it is immutable for the +/// life of the module. +class TargetLibraryAnalysis { +public: + typedef TargetLibraryInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Default construct the library analysis. + /// + /// This will use the module's triple to construct the library info for that + /// module. + TargetLibraryAnalysis() {} + + /// \brief Construct a library analysis with preset info. + /// + /// This will directly copy the preset info into the result without + /// consulting the module's triple. + TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl) + : PresetInfoImpl(std::move(PresetInfoImpl)) {} + + // Move semantics. We spell out the constructors for MSVC. + TargetLibraryAnalysis(TargetLibraryAnalysis &&Arg) + : PresetInfoImpl(std::move(Arg.PresetInfoImpl)), Impls(std::move(Arg.Impls)) {} + TargetLibraryAnalysis &operator=(TargetLibraryAnalysis &&RHS) { + PresetInfoImpl = std::move(RHS.PresetInfoImpl); + Impls = std::move(RHS.Impls); + return *this; + } + + TargetLibraryInfo run(Module &M); + TargetLibraryInfo run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetLibraryAnalysis"; } + +private: + static char PassID; + + Optional<TargetLibraryInfoImpl> PresetInfoImpl; + + StringMap<std::unique_ptr<TargetLibraryInfoImpl>> Impls; + + TargetLibraryInfoImpl &lookupInfoImpl(Triple T); +}; + +class TargetLibraryInfoWrapperPass : public ImmutablePass { + TargetLibraryInfoImpl TLIImpl; + TargetLibraryInfo TLI; + + virtual void anchor(); + +public: + static char ID; + TargetLibraryInfoWrapperPass(); + explicit TargetLibraryInfoWrapperPass(const Triple &T); + explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); + + TargetLibraryInfo &getTLI() { return TLI; } + const TargetLibraryInfo &getTLI() const { return TLI; } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index 4bd5dd8a221e..86bf1549dc78 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -1,4 +1,4 @@ -//===- llvm/Analysis/TargetTransformInfo.h ----------------------*- C++ -*-===// +//===- TargetTransformInfo.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,66 +6,89 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This pass exposes codegen information to IR-level passes. Every -// transformation that uses codegen information is broken into three parts: -// 1. The IR-level analysis pass. -// 2. The IR-level transformation interface which provides the needed -// information. -// 3. Codegen-level implementation which uses target-specific hooks. -// -// This file defines #2, which is the interface that IR-level transformations -// use for querying the codegen. -// +/// \file +/// This pass exposes codegen information to IR-level passes. Every +/// transformation that uses codegen information is broken into three parts: +/// 1. The IR-level analysis pass. +/// 2. The IR-level transformation interface which provides the needed +/// information. +/// 3. Codegen-level implementation which uses target-specific hooks. +/// +/// This file defines #2, which is the interface that IR-level transformations +/// use for querying the codegen. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFO_H #define LLVM_ANALYSIS_TARGETTRANSFORMINFO_H +#include "llvm/ADT/Optional.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" +#include <functional> namespace llvm { class Function; class GlobalValue; class Loop; +class PreservedAnalyses; class Type; class User; class Value; -/// TargetTransformInfo - This pass provides access to the codegen -/// interfaces that are needed for IR-level transformations. +/// \brief Information about a load/store intrinsic defined by the target. +struct MemIntrinsicInfo { + MemIntrinsicInfo() + : ReadMem(false), WriteMem(false), Vol(false), MatchingId(0), + NumMemRefs(0), PtrVal(nullptr) {} + bool ReadMem; + bool WriteMem; + bool Vol; + // Same Id is set by the target for corresponding load/store intrinsics. + unsigned short MatchingId; + int NumMemRefs; + Value *PtrVal; +}; + +/// \brief 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. +public: + /// \brief Construct a TTI object using a type implementing the \c Concept + /// API below. /// - /// 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. - TargetTransformInfo *PrevTTI; + /// This is used by targets to construct a TTI wrapping their target-specific + /// implementaion that encodes appropriate costs for their target. + template <typename T> TargetTransformInfo(T Impl); - /// \brief The top of the stack of TTI analyses available. + /// \brief Construct a baseline TTI object using a minimal implementation of + /// the \c Concept API below. /// - /// This is a convenience routine maintained as TTI analyses become available - /// that complements the PrevTTI delegation chain. When one part of an - /// analysis pass wants to query another part of the analysis pass it can use - /// this to start back at the top of the stack. - TargetTransformInfo *TopTTI; + /// The TTI implementation will reflect the information in the DataLayout + /// provided if non-null. + explicit TargetTransformInfo(const DataLayout *DL); - /// All pass subclasses must in their initializePass routine call - /// pushTTIStack with themselves to update the pointers tracking the previous - /// TTI instance in the analysis group's stack, and the top of the analysis - /// group's stack. - void pushTTIStack(Pass *P); + // Provide move semantics. + TargetTransformInfo(TargetTransformInfo &&Arg); + TargetTransformInfo &operator=(TargetTransformInfo &&RHS); - /// All pass subclasses must call TargetTransformInfo::getAnalysisUsage. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; + // We need to define the destructor out-of-line to define our sub-classes + // out-of-line. + ~TargetTransformInfo(); -public: - /// This class is intended to be subclassed by real implementations. - virtual ~TargetTransformInfo() = 0; + /// \brief Handle the invalidation of this information. + /// + /// When used as a result of \c TargetIRAnalysis this method will be called + /// when the function this was computed for changes. When it returns false, + /// the information is preserved across those changes. + bool invalidate(Function &, const PreservedAnalyses &) { + // FIXME: We should probably in some way ensure that the subtarget + // information for a function hasn't changed. + return false; + } /// \name Generic Target Information /// @{ @@ -86,9 +109,9 @@ public: /// skipped by renaming the registers in the CPU, but they still are encoded /// and thus wouldn't be considered 'free' here. enum TargetCostConstants { - TCC_Free = 0, ///< Expected to fold away in lowering. - TCC_Basic = 1, ///< The cost of a typical 'add' instruction. - TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. + TCC_Free = 0, ///< Expected to fold away in lowering. + TCC_Basic = 1, ///< The cost of a typical 'add' instruction. + TCC_Expensive = 4 ///< The cost of a 'div' instruction on x86. }; /// \brief Estimate the cost of a specific operation when lowered. @@ -105,16 +128,15 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, - Type *OpTy = nullptr) const; + unsigned getOperationCost(unsigned Opcode, Type *Ty, + Type *OpTy = nullptr) const; /// \brief Estimate the cost of a GEP operation when lowered. /// /// The contract for this function is the same as \c getOperationCost except /// that it supports an interface that provides extra information specific to /// the GEP operation. - virtual unsigned getGEPCost(const Value *Ptr, - ArrayRef<const Value *> Operands) const; + unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) const; /// \brief Estimate the cost of a function call when lowered. /// @@ -125,31 +147,31 @@ public: /// This is the most basic query for estimating call cost: it only knows the /// function type and (potentially) the number of arguments at the call site. /// The latter is only interesting for varargs function types. - virtual unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; + unsigned getCallCost(FunctionType *FTy, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload adds the ability to reason about the particular function /// being called in the event it is a library call with special lowering. - virtual unsigned getCallCost(const Function *F, int NumArgs = -1) const; + unsigned getCallCost(const Function *F, int NumArgs = -1) const; /// \brief Estimate the cost of calling a specific function when lowered. /// /// This overload allows specifying a set of candidate argument values. - virtual unsigned getCallCost(const Function *F, - ArrayRef<const Value *> Arguments) const; + unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<Type *> ParamTys) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) const; /// \brief Estimate the cost of an intrinsic when lowered. /// /// Mirrors the \c getCallCost method but uses an intrinsic identifier. - virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, - ArrayRef<const Value *> Arguments) const; + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) const; /// \brief Estimate the cost of a given IR user when lowered. /// @@ -166,13 +188,22 @@ public: /// /// The returned cost is defined in terms of \c TargetCostConstants, see its /// comments for a detailed explanation of the cost values. - virtual unsigned getUserCost(const User *U) const; + unsigned getUserCost(const User *U) const; - /// \brief hasBranchDivergence - Return true if branch divergence exists. + /// \brief Return true if branch divergence exists. + /// /// Branch divergence has a significantly negative impact on GPU performance /// when threads in the same wavefront take different paths due to conditional /// branches. - virtual bool hasBranchDivergence() const; + bool hasBranchDivergence() const; + + /// \brief Returns whether V is a source of divergence. + /// + /// This function provides the target-dependent information for + /// the target-independent DivergenceAnalysis. DivergenceAnalysis first + /// builds the dependency graph, and then runs the reachability algorithm + /// starting with the sources of divergence. + bool isSourceOfDivergence(const Value *V) const; /// \brief Test whether calls to a function lower to actual program function /// calls. @@ -186,7 +217,7 @@ public: /// and execution-speed costs. This would allow modelling the core of this /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. - virtual bool isLoweredToCall(const Function *F) const; + bool isLoweredToCall(const Function *F) const; /// Parameters that control the generic loop unrolling transformation. struct UnrollingPreferences { @@ -196,6 +227,13 @@ public: /// exceed this cost. Set this to UINT_MAX to disable the loop body cost /// restriction. unsigned Threshold; + /// If complete unrolling could help other optimizations (e.g. InstSimplify) + /// to remove N% of instructions, then we can go beyond unroll threshold. + /// This value set the minimal percent for allowing that. + unsigned MinPercentOfOptimized; + /// The absolute cost threshold. We won't go beyond this even if complete + /// unrolling could result in optimizing out 90% of instructions. + unsigned AbsoluteThreshold; /// The cost threshold for the unrolled loop when optimizing for size (set /// to UINT_MAX to disable). unsigned OptSizeThreshold; @@ -203,8 +241,8 @@ public: /// for partial/runtime unrolling (set to UINT_MAX to disable). unsigned PartialThreshold; /// The cost threshold for the unrolled loop when optimizing for size, like - /// OptSizeThreshold, but used for partial/runtime unrolling (set to UINT_MAX - /// to disable). + /// OptSizeThreshold, but used for partial/runtime unrolling (set to + /// UINT_MAX to disable). unsigned PartialOptSizeThreshold; /// A forced unrolling factor (the number of concatenated bodies of the /// original loop in the unrolled loop body). When set to 0, the unrolling @@ -218,18 +256,20 @@ public: unsigned MaxCount; /// Allow partial unrolling (unrolling of loops to expand the size of the /// loop body, not only to eliminate small constant-trip-count loops). - bool Partial; + bool Partial; /// Allow runtime unrolling (unrolling of loops to expand the size of the - /// loop body even when the number of loop iterations is not known at compile - /// time). - bool Runtime; + /// loop body even when the number of loop iterations is not known at + /// compile time). + bool Runtime; + /// Allow emitting expensive instructions (such as divisions) when computing + /// the trip count of a loop for runtime unrolling. + bool AllowExpensiveTripCount; }; /// \brief Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. - virtual void getUnrollingPreferences(const Function *F, Loop *L, - UnrollingPreferences &UP) const; + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; /// @} @@ -244,38 +284,33 @@ public: /// support is considered as "Fast" if it can outperform, or is on a par /// with, SW implementation when the population is sparse; otherwise, it is /// considered as "Slow". - enum PopcntSupportKind { - PSK_Software, - PSK_SlowHardware, - PSK_FastHardware - }; + enum PopcntSupportKind { PSK_Software, PSK_SlowHardware, PSK_FastHardware }; /// \brief 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 Imm) const; + bool isLegalAddImmediate(int64_t Imm) const; /// \brief 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 Imm) const; + bool isLegalICmpImmediate(int64_t Imm) const; /// \brief 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. - virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief Return true if the target works with masked instruction /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. /// AVX-512 architecture will also allow masks for non-consecutive memory /// accesses. - virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const; - virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const; + bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + bool isLegalMaskedLoad(Type *DataType, int Consecutive) const; /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store @@ -283,45 +318,55 @@ public: /// If the AM is supported, the return value must be >= 0. /// If the AM is not supported, it returns a negative value. /// TODO: Handle pre/postinc as well. - virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, - int64_t BaseOffset, bool HasBaseReg, - int64_t Scale) const; + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) const; /// \brief 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; + bool isTruncateFree(Type *Ty1, Type *Ty2) const; + + /// \brief Return true if it is profitable to hoist instruction in the + /// then/else to before if. + bool isProfitableToHoist(Instruction *I) const; /// \brief Return true if this type is legal. - virtual bool isTypeLegal(Type *Ty) const; + bool isTypeLegal(Type *Ty) const; /// \brief Returns the target's jmp_buf alignment in bytes. - virtual unsigned getJumpBufAlignment() const; + unsigned getJumpBufAlignment() const; /// \brief Returns the target's jmp_buf size in bytes. - virtual unsigned getJumpBufSize() const; + unsigned getJumpBufSize() const; /// \brief Return true if switches should be turned into lookup tables for the /// target. - virtual bool shouldBuildLookupTables() const; + bool shouldBuildLookupTables() const; + + /// \brief Don't restrict interleaved unrolling to small loops. + bool enableAggressiveInterleaving(bool LoopHasReductions) const; /// \brief Return hardware support for population count. - virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) const; /// \brief Return true if the hardware has a fast square-root instruction. - virtual bool haveFastSqrt(Type *Ty) const; + bool haveFastSqrt(Type *Ty) const; + + /// \brief Return the expected cost of supporting the floating point operation + /// of the specified type. + unsigned getFPOpCost(Type *Ty) const; /// \brief Return the expected cost of materializing for the given integer /// immediate of the specified type. - virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(const APInt &Imm, Type *Ty) const; /// \brief Return the expected cost of materialization for the given integer /// immediate of the specified type for a given instruction. The cost can be /// zero if the immediate can be folded into the specified instruction. - virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, - Type *Ty) const; - virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, - const APInt &Imm, Type *Ty) const; + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) const; + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) const; /// @} /// \name Vector Target Information @@ -338,10 +383,10 @@ public: /// \brief Additional information about an operand's possible values. enum OperandValueKind { - OK_AnyValue, // Operand can have any value. - OK_UniformValue, // Operand is uniform (splat of a value). - OK_UniformConstantValue, // Operand is uniform constant. - OK_NonUniformConstantValue // Operand is a non uniform constant value. + OK_AnyValue, // Operand can have any value. + OK_UniformValue, // Operand is uniform (splat of a value). + OK_UniformConstantValue, // Operand is uniform constant. + OK_NonUniformConstantValue // Operand is a non uniform constant value. }; /// \brief Additional properties of an operand's values. @@ -350,18 +395,18 @@ 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; + unsigned getNumberOfRegisters(bool Vector) const; /// \return The width of the largest scalar or vector register type. - virtual unsigned getRegisterBitWidth(bool Vector) const; + unsigned getRegisterBitWidth(bool Vector) const; /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaxInterleaveFactor() const; + unsigned getMaxInterleaveFactor(unsigned VF) const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info = OK_AnyValue, OperandValueKind Opd2Info = OK_AnyValue, @@ -371,31 +416,33 @@ public: /// \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 = nullptr) const; + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index = 0, + Type *SubTp = nullptr) const; /// \return The expected cost of cast instructions, such as bitcast, trunc, /// zext, etc. - virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, - Type *Src) const; + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) const; /// \return The expected cost of control-flow related instructions such as /// Phi, Ret, Br. - virtual unsigned getCFInstrCost(unsigned Opcode) const; + unsigned getCFInstrCost(unsigned Opcode) const; /// \returns The expected cost of compare and select instructions. - virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, - Type *CondTy = nullptr) const; + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy = nullptr) 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; + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index = -1) const; /// \return The cost of Load and Store instructions. - virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, - unsigned Alignment, - unsigned AddressSpace) const; + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; + + /// \return The cost of masked Load and Store instructions. + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) const; /// \brief Calculate the cost of performing a vector reduction. /// @@ -410,16 +457,20 @@ public: /// Split: /// (v0, v1, v2, v3) /// ((v0+v2), (v1+v3), undef, undef) - virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, - bool IsPairwiseForm) const; + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) const; /// \returns The cost of Intrinsic instructions. - virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, - ArrayRef<Type *> Tys) const; + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) const; + + /// \returns The cost of Call instructions. + unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> 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; + unsigned getNumberOfParts(Type *Tp) const; /// \returns The cost of the address computation. For most targets this can be /// merged into the instruction indexing mode. Some targets might want to @@ -428,28 +479,399 @@ public: /// The 'IsComplex' parameter is a hint that the address computation is likely /// to involve multiple instructions and as such unlikely to be merged into /// the address indexing mode. - virtual unsigned getAddressComputationCost(Type *Ty, - bool IsComplex = false) const; + unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; /// \returns The cost, if any, of keeping values of the given types alive /// over a callsite. /// /// Some types may require the use of register classes that do not have /// any callee-saved registers, so would require a spill and fill. - virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type*> Tys) const; + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) const; + + /// \returns True if the intrinsic is a supported memory intrinsic. Info + /// will contain additional information - whether the intrinsic may write + /// or read to memory, volatility and the pointer. Info is undefined + /// if false is returned. + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) const; + + /// \returns A value which is the result of the given memory intrinsic. New + /// instructions may be created to extract the result from the given intrinsic + /// memory operation. Returns nullptr if the target cannot create a result + /// from the given intrinsic. + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) const; /// @} - /// Analysis group identification. +private: + /// \brief The abstract base class used to type erase specific TTI + /// implementations. + class Concept; + + /// \brief The template model for the base class which wraps a concrete + /// implementation in a type erased interface. + template <typename T> class Model; + + std::unique_ptr<Concept> TTIImpl; +}; + +class TargetTransformInfo::Concept { +public: + virtual ~Concept() = 0; + + virtual unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; + virtual unsigned getGEPCost(const Value *Ptr, + ArrayRef<const Value *> Operands) = 0; + virtual unsigned getCallCost(FunctionType *FTy, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, int NumArgs) = 0; + virtual unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) = 0; + virtual unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) = 0; + virtual unsigned getUserCost(const User *U) = 0; + virtual bool hasBranchDivergence() = 0; + virtual bool isSourceOfDivergence(const Value *V) = 0; + virtual bool isLoweredToCall(const Function *F) = 0; + virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; + virtual bool isLegalAddImmediate(int64_t Imm) = 0; + virtual bool isLegalICmpImmediate(int64_t Imm) = 0; + virtual bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) = 0; + virtual bool isLegalMaskedLoad(Type *DataType, int Consecutive) = 0; + virtual int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, + int64_t BaseOffset, bool HasBaseReg, + int64_t Scale) = 0; + virtual bool isTruncateFree(Type *Ty1, Type *Ty2) = 0; + virtual bool isProfitableToHoist(Instruction *I) = 0; + virtual bool isTypeLegal(Type *Ty) = 0; + virtual unsigned getJumpBufAlignment() = 0; + virtual unsigned getJumpBufSize() = 0; + virtual bool shouldBuildLookupTables() = 0; + virtual bool enableAggressiveInterleaving(bool LoopHasReductions) = 0; + virtual PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) = 0; + virtual bool haveFastSqrt(Type *Ty) = 0; + virtual unsigned getFPOpCost(Type *Ty) = 0; + virtual unsigned getIntImmCost(const APInt &Imm, Type *Ty) = 0; + virtual unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) = 0; + virtual unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, + const APInt &Imm, Type *Ty) = 0; + virtual unsigned getNumberOfRegisters(bool Vector) = 0; + virtual unsigned getRegisterBitWidth(bool Vector) = 0; + virtual unsigned getMaxInterleaveFactor(unsigned VF) = 0; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) = 0; + virtual unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) = 0; + virtual unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) = 0; + virtual unsigned getCFInstrCost(unsigned Opcode) = 0; + virtual unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) = 0; + virtual unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) = 0; + virtual unsigned getMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, + unsigned Alignment, + unsigned AddressSpace) = 0; + virtual unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) = 0; + virtual unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) = 0; + virtual unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> Tys) = 0; + virtual unsigned getNumberOfParts(Type *Tp) = 0; + virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex) = 0; + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) = 0; + virtual bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) = 0; + virtual Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) = 0; +}; + +template <typename T> +class TargetTransformInfo::Model final : public TargetTransformInfo::Concept { + T Impl; + +public: + Model(T Impl) : Impl(std::move(Impl)) {} + ~Model() override {} + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) override { + return Impl.getOperationCost(Opcode, Ty, OpTy); + } + unsigned getGEPCost(const Value *Ptr, + ArrayRef<const Value *> Operands) override { + return Impl.getGEPCost(Ptr, Operands); + } + unsigned getCallCost(FunctionType *FTy, int NumArgs) override { + return Impl.getCallCost(FTy, NumArgs); + } + unsigned getCallCost(const Function *F, int NumArgs) override { + return Impl.getCallCost(F, NumArgs); + } + unsigned getCallCost(const Function *F, + ArrayRef<const Value *> Arguments) override { + return Impl.getCallCost(F, Arguments); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) override { + return Impl.getIntrinsicCost(IID, RetTy, ParamTys); + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) override { + return Impl.getIntrinsicCost(IID, RetTy, Arguments); + } + unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); } + bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); } + bool isSourceOfDivergence(const Value *V) override { + return Impl.isSourceOfDivergence(V); + } + bool isLoweredToCall(const Function *F) override { + return Impl.isLoweredToCall(F); + } + void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) override { + return Impl.getUnrollingPreferences(L, UP); + } + bool isLegalAddImmediate(int64_t Imm) override { + return Impl.isLegalAddImmediate(Imm); + } + bool isLegalICmpImmediate(int64_t Imm) override { + return Impl.isLegalICmpImmediate(Imm); + } + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, + Scale); + } + bool isLegalMaskedStore(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedStore(DataType, Consecutive); + } + bool isLegalMaskedLoad(Type *DataType, int Consecutive) override { + return Impl.isLegalMaskedLoad(DataType, Consecutive); + } + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) override { + return Impl.getScalingFactorCost(Ty, BaseGV, BaseOffset, HasBaseReg, Scale); + } + bool isTruncateFree(Type *Ty1, Type *Ty2) override { + return Impl.isTruncateFree(Ty1, Ty2); + } + bool isProfitableToHoist(Instruction *I) override { + return Impl.isProfitableToHoist(I); + } + bool isTypeLegal(Type *Ty) override { return Impl.isTypeLegal(Ty); } + unsigned getJumpBufAlignment() override { return Impl.getJumpBufAlignment(); } + unsigned getJumpBufSize() override { return Impl.getJumpBufSize(); } + bool shouldBuildLookupTables() override { + return Impl.shouldBuildLookupTables(); + } + bool enableAggressiveInterleaving(bool LoopHasReductions) override { + return Impl.enableAggressiveInterleaving(LoopHasReductions); + } + PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) override { + return Impl.getPopcntSupport(IntTyWidthInBit); + } + bool haveFastSqrt(Type *Ty) override { return Impl.haveFastSqrt(Ty); } + + unsigned getFPOpCost(Type *Ty) override { + return Impl.getFPOpCost(Ty); + } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) override { + return Impl.getIntImmCost(Imm, Ty); + } + unsigned getIntImmCost(unsigned Opc, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(Opc, Idx, Imm, Ty); + } + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) override { + return Impl.getIntImmCost(IID, Idx, Imm, Ty); + } + unsigned getNumberOfRegisters(bool Vector) override { + return Impl.getNumberOfRegisters(Vector); + } + unsigned getRegisterBitWidth(bool Vector) override { + return Impl.getRegisterBitWidth(Vector); + } + unsigned getMaxInterleaveFactor(unsigned VF) override { + return Impl.getMaxInterleaveFactor(VF); + } + unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, OperandValueKind Opd1Info, + OperandValueKind Opd2Info, + OperandValueProperties Opd1PropInfo, + OperandValueProperties Opd2PropInfo) override { + return Impl.getArithmeticInstrCost(Opcode, Ty, Opd1Info, Opd2Info, + Opd1PropInfo, Opd2PropInfo); + } + unsigned getShuffleCost(ShuffleKind Kind, Type *Tp, int Index, + Type *SubTp) override { + return Impl.getShuffleCost(Kind, Tp, Index, SubTp); + } + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) override { + return Impl.getCastInstrCost(Opcode, Dst, Src); + } + unsigned getCFInstrCost(unsigned Opcode) override { + return Impl.getCFInstrCost(Opcode); + } + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, + Type *CondTy) override { + return Impl.getCmpSelInstrCost(Opcode, ValTy, CondTy); + } + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, + unsigned Index) override { + return Impl.getVectorInstrCost(Opcode, Val, Index); + } + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) override { + return Impl.getMaskedMemoryOpCost(Opcode, Src, Alignment, AddressSpace); + } + unsigned getReductionCost(unsigned Opcode, Type *Ty, + bool IsPairwiseForm) override { + return Impl.getReductionCost(Opcode, Ty, IsPairwiseForm); + } + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) override { + return Impl.getIntrinsicInstrCost(ID, RetTy, Tys); + } + unsigned getCallInstrCost(Function *F, Type *RetTy, + ArrayRef<Type *> Tys) override { + return Impl.getCallInstrCost(F, RetTy, Tys); + } + unsigned getNumberOfParts(Type *Tp) override { + return Impl.getNumberOfParts(Tp); + } + unsigned getAddressComputationCost(Type *Ty, bool IsComplex) override { + return Impl.getAddressComputationCost(Ty, IsComplex); + } + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) override { + return Impl.getCostOfKeepingLiveOverCall(Tys); + } + bool getTgtMemIntrinsic(IntrinsicInst *Inst, + MemIntrinsicInfo &Info) override { + return Impl.getTgtMemIntrinsic(Inst, Info); + } + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) override { + return Impl.getOrCreateResultFromMemIntrinsic(Inst, ExpectedType); + } +}; + +template <typename T> +TargetTransformInfo::TargetTransformInfo(T Impl) + : TTIImpl(new Model<T>(Impl)) {} + +/// \brief Analysis pass providing the \c TargetTransformInfo. +/// +/// The core idea of the TargetIRAnalysis is to expose an interface through +/// which LLVM targets can analyze and provide information about the middle +/// end's target-independent IR. This supports use cases such as target-aware +/// cost modeling of IR constructs. +/// +/// This is a function analysis because much of the cost modeling for targets +/// is done in a subtarget specific way and LLVM supports compiling different +/// functions targeting different subtargets in order to support runtime +/// dispatch according to the observed subtarget. +class TargetIRAnalysis { +public: + typedef TargetTransformInfo Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "TargetIRAnalysis"; } + + /// \brief Default construct a target IR analysis. + /// + /// This will use the module's datalayout to construct a baseline + /// conservative TTI result. + TargetIRAnalysis(); + + /// \brief Construct an IR analysis pass around a target-provide callback. + /// + /// The callback will be called with a particular function for which the TTI + /// is needed and must return a TTI object for that function. + TargetIRAnalysis(std::function<Result(Function &)> TTICallback); + + // Value semantics. We spell out the constructors for MSVC. + TargetIRAnalysis(const TargetIRAnalysis &Arg) + : TTICallback(Arg.TTICallback) {} + TargetIRAnalysis(TargetIRAnalysis &&Arg) + : TTICallback(std::move(Arg.TTICallback)) {} + TargetIRAnalysis &operator=(const TargetIRAnalysis &RHS) { + TTICallback = RHS.TTICallback; + return *this; + } + TargetIRAnalysis &operator=(TargetIRAnalysis &&RHS) { + TTICallback = std::move(RHS.TTICallback); + return *this; + } + + Result run(Function &F); + +private: + static char PassID; + + /// \brief The callback used to produce a result. + /// + /// We use a completely opaque callback so that targets can provide whatever + /// mechanism they desire for constructing the TTI for a given function. + /// + /// FIXME: Should we really use std::function? It's relatively inefficient. + /// It might be possible to arrange for even stateful callbacks to outlive + /// the analysis and thus use a function_ref which would be lighter weight. + /// This may also be less error prone as the callback is likely to reference + /// the external TargetMachine, and that reference needs to never dangle. + std::function<Result(Function &)> TTICallback; + + /// \brief Helper function used as the callback in the default constructor. + static Result getDefaultTTI(Function &F); +}; + +/// \brief Wrapper pass for TargetTransformInfo. +/// +/// This pass can be constructed from a TTI object which it stores internally +/// and is queried by passes. +class TargetTransformInfoWrapperPass : public ImmutablePass { + TargetIRAnalysis TIRA; + Optional<TargetTransformInfo> TTI; + + virtual void anchor(); + +public: static char ID; + + /// \brief We must provide a default constructor for the pass but it should + /// never be used. + /// + /// Use the constructor below or call one of the creation routines. + TargetTransformInfoWrapperPass(); + + explicit TargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); + + TargetTransformInfo &getTTI(Function &F); }; -/// \brief Create the base case instance of a pass in the TTI analysis group. +/// \brief Create an analysis pass wrapper around a TTI object. /// -/// This class provides the base case for the stack of TTI analyzes. It doesn't -/// delegate to anything and uses the STTI and VTTI objects passed in to -/// satisfy the queries. -ImmutablePass *createNoTargetTransformInfoPass(); +/// This analysis pass just holds the TTI instance and makes it available to +/// clients. +ImmutablePass *createTargetTransformInfoWrapperPass(TargetIRAnalysis TIRA); } // End llvm namespace diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h new file mode 100644 index 000000000000..253319ccd441 --- /dev/null +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -0,0 +1,441 @@ +//===- TargetTransformInfoImpl.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file provides helpers for the implementation of +/// a TargetTransformInfo-conforming class. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H +#define LLVM_ANALYSIS_TARGETTRANSFORMINFOIMPL_H + +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Operator.h" +#include "llvm/IR/Type.h" + +namespace llvm { + +/// \brief Base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +class TargetTransformInfoImplBase { +protected: + typedef TargetTransformInfo TTI; + + const DataLayout *DL; + + explicit TargetTransformInfoImplBase(const DataLayout *DL) + : DL(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplBase(const TargetTransformInfoImplBase &Arg) + : DL(Arg.DL) {} + TargetTransformInfoImplBase(TargetTransformInfoImplBase &&Arg) + : DL(std::move(Arg.DL)) {} + TargetTransformInfoImplBase & + operator=(const TargetTransformInfoImplBase &RHS) { + DL = RHS.DL; + return *this; + } + TargetTransformInfoImplBase &operator=(TargetTransformInfoImplBase &&RHS) { + DL = std::move(RHS.DL); + return *this; + } + + unsigned getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) { + switch (Opcode) { + default: + // By default, just classify everything as 'basic'. + return TTI::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 TTI::TCC_Free; + + // Otherwise, the default basic cost is used. + return TTI::TCC_Basic; + + case Instruction::IntToPtr: { + if (!DL) + return TTI::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 TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::TCC_Basic; + } + case Instruction::PtrToInt: { + if (!DL) + return TTI::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 TTI::TCC_Free; + + // Otherwise it's not a no-op. + return TTI::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 TTI::TCC_Free; + + return TTI::TCC_Basic; + } + } + + unsigned getGEPCost(const Value *Ptr, ArrayRef<const Value *> Operands) { + // 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 TTI::TCC_Basic; + + return TTI::TCC_Free; + } + + unsigned getCallCost(FunctionType *FTy, int NumArgs) { + 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 TTI::TCC_Basic * (NumArgs + 1); + } + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<Type *> ParamTys) { + 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 TTI::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 TTI::TCC_Free; + } + } + + bool hasBranchDivergence() { return false; } + + bool isSourceOfDivergence(const Value *V) { return false; } + + bool isLoweredToCall(const Function *F) { + // 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(Loop *, TTI::UnrollingPreferences &) {} + + bool isLegalAddImmediate(int64_t Imm) { return false; } + + bool isLegalICmpImmediate(int64_t Imm) { return false; } + + bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // Guess that only reg and reg+reg addressing is allowed. This heuristic is + // taken from the implementation of LSR. + return !BaseGV && BaseOffset == 0 && (Scale == 0 || Scale == 1); + } + + bool isLegalMaskedStore(Type *DataType, int Consecutive) { return false; } + + bool isLegalMaskedLoad(Type *DataType, int Consecutive) { return false; } + + int getScalingFactorCost(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset, + bool HasBaseReg, int64_t Scale) { + // 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) { return false; } + + bool isProfitableToHoist(Instruction *I) { return true; } + + bool isTypeLegal(Type *Ty) { return false; } + + unsigned getJumpBufAlignment() { return 0; } + + unsigned getJumpBufSize() { return 0; } + + bool shouldBuildLookupTables() { return true; } + + bool enableAggressiveInterleaving(bool LoopHasReductions) { return false; } + + TTI::PopcntSupportKind getPopcntSupport(unsigned IntTyWidthInBit) { + return TTI::PSK_Software; + } + + bool haveFastSqrt(Type *Ty) { return false; } + + unsigned getFPOpCost(Type *Ty) { return TargetTransformInfo::TCC_Basic; } + + unsigned getIntImmCost(const APInt &Imm, Type *Ty) { return TTI::TCC_Basic; } + + unsigned getIntImmCost(unsigned Opcode, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getIntImmCost(Intrinsic::ID IID, unsigned Idx, const APInt &Imm, + Type *Ty) { + return TTI::TCC_Free; + } + + unsigned getNumberOfRegisters(bool Vector) { return 8; } + + unsigned getRegisterBitWidth(bool Vector) { return 32; } + + unsigned getMaxInterleaveFactor(unsigned VF) { return 1; } + + unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, + TTI::OperandValueKind Opd1Info, + TTI::OperandValueKind Opd2Info, + TTI::OperandValueProperties Opd1PropInfo, + TTI::OperandValueProperties Opd2PropInfo) { + return 1; + } + + unsigned getShuffleCost(TTI::ShuffleKind Kind, Type *Ty, int Index, + Type *SubTp) { + return 1; + } + + unsigned getCastInstrCost(unsigned Opcode, Type *Dst, Type *Src) { return 1; } + + unsigned getCFInstrCost(unsigned Opcode) { return 1; } + + unsigned getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy) { + return 1; + } + + unsigned getVectorInstrCost(unsigned Opcode, Type *Val, unsigned Index) { + return 1; + } + + unsigned getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getMaskedMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, + unsigned AddressSpace) { + return 1; + } + + unsigned getIntrinsicInstrCost(Intrinsic::ID ID, Type *RetTy, + ArrayRef<Type *> Tys) { + return 1; + } + + unsigned getCallInstrCost(Function *F, Type *RetTy, ArrayRef<Type *> Tys) { + return 1; + } + + unsigned getNumberOfParts(Type *Tp) { return 0; } + + unsigned getAddressComputationCost(Type *Tp, bool) { return 0; } + + unsigned getReductionCost(unsigned, Type *, bool) { return 1; } + + unsigned getCostOfKeepingLiveOverCall(ArrayRef<Type *> Tys) { return 0; } + + bool getTgtMemIntrinsic(IntrinsicInst *Inst, MemIntrinsicInfo &Info) { + return false; + } + + Value *getOrCreateResultFromMemIntrinsic(IntrinsicInst *Inst, + Type *ExpectedType) { + return nullptr; + } +}; + +/// \brief CRTP base class for use as a mix-in that aids implementing +/// a TargetTransformInfo-compatible class. +template <typename T> +class TargetTransformInfoImplCRTPBase : public TargetTransformInfoImplBase { +private: + typedef TargetTransformInfoImplBase BaseT; + +protected: + explicit TargetTransformInfoImplCRTPBase(const DataLayout *DL) + : BaseT(DL) {} + +public: + // Provide value semantics. MSVC requires that we spell all of these out. + TargetTransformInfoImplCRTPBase(const TargetTransformInfoImplCRTPBase &Arg) + : BaseT(static_cast<const BaseT &>(Arg)) {} + TargetTransformInfoImplCRTPBase(TargetTransformInfoImplCRTPBase &&Arg) + : BaseT(std::move(static_cast<BaseT &>(Arg))) {} + TargetTransformInfoImplCRTPBase & + operator=(const TargetTransformInfoImplCRTPBase &RHS) { + BaseT::operator=(static_cast<const BaseT &>(RHS)); + return *this; + } + TargetTransformInfoImplCRTPBase & + operator=(TargetTransformInfoImplCRTPBase &&RHS) { + BaseT::operator=(std::move(static_cast<BaseT &>(RHS))); + return *this; + } + + using BaseT::getCallCost; + + unsigned getCallCost(const Function *F, int NumArgs) { + 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 = F->getIntrinsicID()) { + FunctionType *FTy = F->getFunctionType(); + SmallVector<Type *, 8> ParamTys(FTy->param_begin(), FTy->param_end()); + return static_cast<T *>(this) + ->getIntrinsicCost(IID, FTy->getReturnType(), ParamTys); + } + + if (!static_cast<T *>(this)->isLoweredToCall(F)) + return TTI::TCC_Basic; // Give a basic cost if it will be lowered + // directly. + + return static_cast<T *>(this)->getCallCost(F->getFunctionType(), NumArgs); + } + + unsigned getCallCost(const Function *F, ArrayRef<const Value *> Arguments) { + // 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 static_cast<T *>(this)->getCallCost(F, Arguments.size()); + } + + using BaseT::getIntrinsicCost; + + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, + ArrayRef<const Value *> Arguments) { + // 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 static_cast<T *>(this)->getIntrinsicCost(IID, RetTy, ParamTys); + } + + unsigned getUserCost(const User *U) { + if (isa<PHINode>(U)) + return TTI::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 static_cast<T *>(this) + ->getGEPCost(GEP->getPointerOperand(), Indices); + } + + if (auto CS = ImmutableCallSite(U)) { + const Function *F = CS.getCalledFunction(); + if (!F) { + // Just use the called value type. + Type *FTy = CS.getCalledValue()->getType()->getPointerElementType(); + return static_cast<T *>(this) + ->getCallCost(cast<FunctionType>(FTy), CS.arg_size()); + } + + SmallVector<const Value *, 8> Arguments(CS.arg_begin(), CS.arg_end()); + return static_cast<T *>(this)->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 TTI::TCC_Free; + } + + return static_cast<T *>(this)->getOperationCost( + Operator::getOpcode(U), U->getType(), + U->getNumOperands() == 1 ? U->getOperand(0)->getType() : nullptr); + } +}; +} + +#endif diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index cc588381727d..653821d02271 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -16,6 +16,7 @@ #define LLVM_ANALYSIS_VALUETRACKING_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/IR/Instruction.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -28,17 +29,18 @@ namespace llvm { class AssumptionCache; class DominatorTree; class TargetLibraryInfo; + class LoopInfo; /// Determine which bits of V are known to be either zero or one and return /// them in the KnownZero/KnownOne bit sets. /// /// This function is defined on values with integer type, values with pointer - /// type (but only if TD is non-null), and vectors of integers. In the case + /// type, and vectors of integers. In the case /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0, + const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -46,11 +48,16 @@ namespace llvm { /// \p KnownZero the set of bits that are known to be zero void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, APInt &KnownZero); + /// Returns true if LHS and RHS have no common bits set. + bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0, + const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -60,7 +67,8 @@ namespace llvm { /// element is known to be a power of two when defined. Supports values with /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. - bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, + bool isKnownToBeAPowerOfTwo(Value *V, const DataLayout &DL, + bool OrZero = false, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -69,8 +77,8 @@ namespace llvm { /// when defined. For vectors return true if every element is known to be /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. - bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, - unsigned Depth = 0, AssumptionCache *AC = nullptr, + bool isKnownNonZero(Value *V, const DataLayout &DL, unsigned Depth = 0, + AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -79,13 +87,12 @@ namespace llvm { /// zero for bits that V cannot have. /// /// This function is defined on values with integer type, values with pointer - /// type (but only if TD is non-null), and vectors of integers. In the case + /// type, and vectors of integers. In the case /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, - const DataLayout *TD = nullptr, unsigned Depth = 0, - AssumptionCache *AC = nullptr, + bool MaskedValueIsZero(Value *V, const APInt &Mask, const DataLayout &DL, + unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -97,7 +104,7 @@ namespace llvm { /// /// 'Op' must have a scalar integer type. /// - unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, + unsigned ComputeNumSignBits(Value *Op, const DataLayout &DL, unsigned Depth = 0, AssumptionCache *AC = nullptr, const Instruction *CxtI = nullptr, const DominatorTree *DT = nullptr); @@ -116,6 +123,11 @@ namespace llvm { /// bool CannotBeNegativeZero(const Value *V, unsigned Depth = 0); + /// CannotBeOrderedLessThanZero - Return true if we can prove that the + /// specified FP value is either a NaN or never less than 0.0. + /// + bool CannotBeOrderedLessThanZero(const Value *V, unsigned Depth = 0); + /// isBytewiseValue - If the specified value can be set by repeating the same /// byte in memory, return the i8 value that it is represented with. This is /// true for all i8 values obviously, but is also true for i32 0, i32 -1, @@ -137,11 +149,12 @@ namespace llvm { /// it can be expressed as a base pointer plus a constant offset. Return the /// base and offset to the caller. Value *GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset, - const DataLayout *TD); + const DataLayout &DL); static inline const Value * GetPointerBaseWithConstantOffset(const Value *Ptr, int64_t &Offset, - const DataLayout *TD) { - return GetPointerBaseWithConstantOffset(const_cast<Value*>(Ptr), Offset,TD); + const DataLayout &DL) { + return GetPointerBaseWithConstantOffset(const_cast<Value *>(Ptr), Offset, + DL); } /// getConstantStringInfo - This function computes the length of a @@ -162,26 +175,59 @@ namespace llvm { /// being addressed. Note that the returned value has pointer type if the /// specified value does. If the MaxLookup value is non-zero, it limits the /// number of instructions to be stripped off. - Value *GetUnderlyingObject(Value *V, const DataLayout *TD = nullptr, + Value *GetUnderlyingObject(Value *V, const DataLayout &DL, unsigned MaxLookup = 6); - static inline const Value * - GetUnderlyingObject(const Value *V, const DataLayout *TD = nullptr, - unsigned MaxLookup = 6) { - return GetUnderlyingObject(const_cast<Value *>(V), TD, MaxLookup); + static inline const Value *GetUnderlyingObject(const Value *V, + const DataLayout &DL, + unsigned MaxLookup = 6) { + return GetUnderlyingObject(const_cast<Value *>(V), DL, MaxLookup); } - /// GetUnderlyingObjects - This method is similar to GetUnderlyingObject - /// except that it can look through phi and select instructions and return - /// multiple objects. - void GetUnderlyingObjects(Value *V, - SmallVectorImpl<Value *> &Objects, - const DataLayout *TD = nullptr, + /// \brief This method is similar to GetUnderlyingObject except that it can + /// look through phi and select instructions and return multiple objects. + /// + /// If LoopInfo is passed, loop phis are further analyzed. If a pointer + /// accesses different objects in each iteration, we don't look through the + /// phi node. E.g. consider this loop nest: + /// + /// int **A; + /// for (i) + /// for (j) { + /// A[i][j] = A[i-1][j] * B[j] + /// } + /// + /// This is transformed by Load-PRE to stash away A[i] for the next iteration + /// of the outer loop: + /// + /// Curr = A[0]; // Prev_0 + /// for (i: 1..N) { + /// Prev = Curr; // Prev = PHI (Prev_0, Curr) + /// Curr = A[i]; + /// for (j: 0..N) { + /// Curr[j] = Prev[j] * B[j] + /// } + /// } + /// + /// Since A[i] and A[i-1] are independent pointers, getUnderlyingObjects + /// should not assume that Curr and Prev share the same underlying object thus + /// it shouldn't look through the phi above. + void GetUnderlyingObjects(Value *V, SmallVectorImpl<Value *> &Objects, + const DataLayout &DL, LoopInfo *LI = nullptr, unsigned MaxLookup = 6); /// onlyUsedByLifetimeMarkers - Return true if the only users of this pointer /// are lifetime markers. bool onlyUsedByLifetimeMarkers(const Value *V); + /// isDereferenceablePointer - Return true if this is always a dereferenceable + /// pointer. If the context instruction is specified perform context-sensitive + /// analysis and return true if the pointer is dereferenceable at the + /// specified instruction. + bool isDereferenceablePointer(const Value *V, const DataLayout &DL, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// isSafeToSpeculativelyExecute - Return true if the instruction does not /// have any effects besides calculating the result and does not have /// undefined behavior. @@ -195,37 +241,82 @@ namespace llvm { /// memory leak. It also returns false for instructions related to control /// flow, specifically terminators and PHI nodes. /// - /// This method only looks at the instruction itself and its operands, so if - /// this method returns true, it is safe to move the instruction as long as - /// the correct dominance relationships for the operands and users hold. - /// However, this method can return true for instructions that read memory; + /// If the CtxI is specified this method performs context-sensitive analysis + /// and returns true if it is safe to execute the instruction immediately + /// before the CtxI. + /// + /// If the CtxI is NOT specified this method only looks at the instruction + /// itself and its operands, so if this method returns true, it is safe to + /// move the instruction as long as the correct dominance relationships for + /// the operands and users hold. + /// + /// This method can return true for instructions that read memory; /// for such instructions, moving them may change the resulting value. bool isSafeToSpeculativelyExecute(const Value *V, - const DataLayout *TD = nullptr); + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); /// isKnownNonNull - Return true if this pointer couldn't possibly be null by /// its definition. This returns true for allocas, non-extern-weak globals /// and byval arguments. bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); + /// isKnownNonNullAt - Return true if this pointer couldn't possibly be null. + /// If the context instruction is specified perform context-sensitive analysis + /// and return true if the pointer couldn't possibly be null at the specified + /// instruction. + bool isKnownNonNullAt(const Value *V, + const Instruction *CtxI = nullptr, + const DominatorTree *DT = nullptr, + const TargetLibraryInfo *TLI = nullptr); + /// Return true if it is valid to use the assumptions provided by an /// assume intrinsic, I, at the point in the control-flow identified by the /// context instruction, CxtI. bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, - const DataLayout *DL = nullptr, const DominatorTree *DT = nullptr); enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, - const DataLayout *DL, + const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, - const DataLayout *DL, + const DataLayout &DL, AssumptionCache *AC, const Instruction *CxtI, const DominatorTree *DT); + + /// \brief Specific patterns of select instructions we can match. + enum SelectPatternFlavor { + SPF_UNKNOWN = 0, + SPF_SMIN, // Signed minimum + SPF_UMIN, // Unsigned minimum + SPF_SMAX, // Signed maximum + SPF_UMAX, // Unsigned maximum + SPF_ABS, // Absolute value + SPF_NABS // Negated absolute value + }; + /// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind + /// and providing the out parameter results if we successfully match. + /// + /// If CastOp is not nullptr, also match MIN/MAX idioms where the type does + /// not match that of the original select. If this is the case, the cast + /// operation (one of Trunc,SExt,Zext) that must be done to transform the + /// type of LHS and RHS into the type of V is returned in CastOp. + /// + /// For example: + /// %1 = icmp slt i32 %a, i32 4 + /// %2 = sext i32 %a to i64 + /// %3 = select i1 %1, i64 %2, i64 4 + /// + /// -> LHS = %a, RHS = i32 4, *CastOp = Instruction::SExt + /// + SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS, + Instruction::CastOps *CastOp = nullptr); + } // end namespace llvm #endif |