diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:10 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-07-19 07:02:10 +0000 |
commit | 93c91e39b29142dec1d03a30df9f6e757f56c193 (patch) | |
tree | 33a9b014a327e64450b3c9ed46d8c5bdb78ad345 /include | |
parent | ca089b24d48ef6fa8da2d0bb8c25bb802c4a95c0 (diff) | |
download | src-93c91e39b29142dec1d03a30df9f6e757f56c193.tar.gz src-93c91e39b29142dec1d03a30df9f6e757f56c193.zip |
Vendor import of llvm trunk r308421:vendor/llvm/llvm-trunk-r308421
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=321184
svn path=/vendor/llvm/llvm-trunk-r308421/; revision=321185; tag=vendor/llvm/llvm-trunk-r308421
Diffstat (limited to 'include')
61 files changed, 1301 insertions, 601 deletions
diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index 8cae63c3c869..b566aeaf1fd6 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -29,9 +29,9 @@ namespace llvm { /// DominanceFrontierBase - Common base class for computing forward and inverse /// dominance frontiers for a function. /// -template <class BlockT> +template <class BlockT, bool IsPostDom> class DominanceFrontierBase { -public: + public: typedef std::set<BlockT *> DomSetType; // Dom set for a bb typedef std::map<BlockT *, DomSetType> DomSetMapType; // Dom set map @@ -40,10 +40,10 @@ protected: DomSetMapType Frontiers; std::vector<BlockT *> Roots; - const bool IsPostDominators; + static constexpr bool IsPostDominators = IsPostDom; -public: - DominanceFrontierBase(bool isPostDom) : IsPostDominators(isPostDom) {} + public: + DominanceFrontierBase() {} /// getRoots - Return the root blocks of the current CFG. This may include /// multiple blocks if we are computing post dominators. For forward @@ -96,7 +96,7 @@ public: /// compare - Return true if the other dominance frontier base matches /// this dominance frontier base. Otherwise return false. - bool compare(DominanceFrontierBase<BlockT> &Other) const; + bool compare(DominanceFrontierBase &Other) const; /// print - Convert to human readable form /// @@ -113,22 +113,21 @@ public: /// used to compute a forward dominator frontiers. /// template <class BlockT> -class ForwardDominanceFrontierBase : public DominanceFrontierBase<BlockT> { -private: +class ForwardDominanceFrontierBase + : public DominanceFrontierBase<BlockT, false> { + private: typedef GraphTraits<BlockT *> BlockTraits; public: - typedef DominatorTreeBase<BlockT> DomTreeT; - typedef DomTreeNodeBase<BlockT> DomTreeNodeT; - typedef typename DominanceFrontierBase<BlockT>::DomSetType DomSetType; - - ForwardDominanceFrontierBase() : DominanceFrontierBase<BlockT>(false) {} - - void analyze(DomTreeT &DT) { - this->Roots = DT.getRoots(); - assert(this->Roots.size() == 1 && - "Only one entry block for forward domfronts!"); - calculate(DT, DT[this->Roots[0]]); + typedef DomTreeBase<BlockT> DomTreeT; + typedef DomTreeNodeBase<BlockT> DomTreeNodeT; + typedef typename DominanceFrontierBase<BlockT, false>::DomSetType DomSetType; + + void analyze(DomTreeT &DT) { + this->Roots = DT.getRoots(); + assert(this->Roots.size() == 1 && + "Only one entry block for forward domfronts!"); + calculate(DT, DT[this->Roots[0]]); } const DomSetType &calculate(const DomTreeT &DT, const DomTreeNodeT *Node); @@ -136,15 +135,16 @@ public: class DominanceFrontier : public ForwardDominanceFrontierBase<BasicBlock> { public: - typedef DominatorTreeBase<BasicBlock> DomTreeT; - typedef DomTreeNodeBase<BasicBlock> DomTreeNodeT; - typedef DominanceFrontierBase<BasicBlock>::DomSetType DomSetType; - typedef DominanceFrontierBase<BasicBlock>::iterator iterator; - typedef DominanceFrontierBase<BasicBlock>::const_iterator const_iterator; - - /// Handle invalidation explicitly. - bool invalidate(Function &F, const PreservedAnalyses &PA, - FunctionAnalysisManager::Invalidator &); + typedef DomTreeBase<BasicBlock> DomTreeT; + typedef DomTreeNodeBase<BasicBlock> DomTreeNodeT; + typedef DominanceFrontierBase<BasicBlock, false>::DomSetType DomSetType; + typedef DominanceFrontierBase<BasicBlock, false>::iterator iterator; + typedef DominanceFrontierBase<BasicBlock, false>::const_iterator + const_iterator; + + /// Handle invalidation explicitly. + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &); }; class DominanceFrontierWrapperPass : public FunctionPass { @@ -168,7 +168,8 @@ public: void dump() const; }; -extern template class DominanceFrontierBase<BasicBlock>; +extern template class DominanceFrontierBase<BasicBlock, false>; +extern template class DominanceFrontierBase<BasicBlock, true>; extern template class ForwardDominanceFrontierBase<BasicBlock>; /// \brief Analysis pass which computes a \c DominanceFrontier. diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 9f8cacc24f2c..5093b975e709 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -39,33 +39,33 @@ public: const DomTreeNodeT *parentNode; }; -template <class BlockT> -void DominanceFrontierBase<BlockT>::removeBlock(BlockT *BB) { +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::removeBlock(BlockT *BB) { assert(find(BB) != end() && "Block is not in DominanceFrontier!"); for (iterator I = begin(), E = end(); I != E; ++I) I->second.erase(BB); Frontiers.erase(BB); } -template <class BlockT> -void DominanceFrontierBase<BlockT>::addToFrontier(iterator I, - BlockT *Node) { +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::addToFrontier(iterator I, + BlockT *Node) { assert(I != end() && "BB is not in DominanceFrontier!"); assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); I->second.erase(Node); } -template <class BlockT> -void DominanceFrontierBase<BlockT>::removeFromFrontier(iterator I, - BlockT *Node) { +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::removeFromFrontier( + iterator I, BlockT *Node) { assert(I != end() && "BB is not in DominanceFrontier!"); assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); I->second.erase(Node); } -template <class BlockT> -bool DominanceFrontierBase<BlockT>::compareDomSet(DomSetType &DS1, - const DomSetType &DS2) const { +template <class BlockT, bool IsPostDom> +bool DominanceFrontierBase<BlockT, IsPostDom>::compareDomSet( + DomSetType &DS1, const DomSetType &DS2) const { std::set<BlockT *> tmpSet; for (BlockT *BB : DS2) tmpSet.insert(BB); @@ -88,9 +88,9 @@ bool DominanceFrontierBase<BlockT>::compareDomSet(DomSetType &DS1, return false; } -template <class BlockT> -bool DominanceFrontierBase<BlockT>::compare( - DominanceFrontierBase<BlockT> &Other) const { +template <class BlockT, bool IsPostDom> +bool DominanceFrontierBase<BlockT, IsPostDom>::compare( + DominanceFrontierBase<BlockT, IsPostDom> &Other) const { DomSetMapType tmpFrontiers; for (typename DomSetMapType::const_iterator I = Other.begin(), E = Other.end(); @@ -118,8 +118,8 @@ bool DominanceFrontierBase<BlockT>::compare( return false; } -template <class BlockT> -void DominanceFrontierBase<BlockT>::print(raw_ostream &OS) const { +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::print(raw_ostream &OS) const { for (const_iterator I = begin(), E = end(); I != E; ++I) { OS << " DomFrontier for BB "; if (I->first) @@ -142,8 +142,8 @@ void DominanceFrontierBase<BlockT>::print(raw_ostream &OS) const { } #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -template <class BlockT> -void DominanceFrontierBase<BlockT>::dump() const { +template <class BlockT, bool IsPostDom> +void DominanceFrontierBase<BlockT, IsPostDom>::dump() const { print(dbgs()); } #endif diff --git a/include/llvm/Analysis/IteratedDominanceFrontier.h b/include/llvm/Analysis/IteratedDominanceFrontier.h index bd74d6bd14c3..edaf4e9025bc 100644 --- a/include/llvm/Analysis/IteratedDominanceFrontier.h +++ b/include/llvm/Analysis/IteratedDominanceFrontier.h @@ -42,11 +42,11 @@ namespace llvm { /// By default, liveness is not used to prune the IDF computation. /// The template parameters should be either BasicBlock* or Inverse<BasicBlock /// *>, depending on if you want the forward or reverse IDF. -template <class NodeTy> +template <class NodeTy, bool IsPostDom> class IDFCalculator { - -public: - IDFCalculator(DominatorTreeBase<BasicBlock> &DT) : DT(DT), useLiveIn(false) {} + public: + IDFCalculator(DominatorTreeBase<BasicBlock, IsPostDom> &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 @@ -84,12 +84,12 @@ public: void calculate(SmallVectorImpl<BasicBlock *> &IDFBlocks); private: - DominatorTreeBase<BasicBlock> &DT; - bool useLiveIn; - const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks; - const SmallPtrSetImpl<BasicBlock *> *DefBlocks; + DominatorTreeBase<BasicBlock, IsPostDom> &DT; + bool useLiveIn; + const SmallPtrSetImpl<BasicBlock *> *LiveInBlocks; + const SmallPtrSetImpl<BasicBlock *> *DefBlocks; }; -typedef IDFCalculator<BasicBlock *> ForwardIDFCalculator; -typedef IDFCalculator<Inverse<BasicBlock *>> ReverseIDFCalculator; +typedef IDFCalculator<BasicBlock *, false> ForwardIDFCalculator; +typedef IDFCalculator<Inverse<BasicBlock *>, true> ReverseIDFCalculator; } #endif diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 3a052761ad7d..a025f2275fb4 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -43,6 +43,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" @@ -908,7 +909,7 @@ public: /// This sets up the graph and computes all of the entry points of the graph. /// No function definitions are scanned until their nodes in the graph are /// requested during traversal. - LazyCallGraph(Module &M); + LazyCallGraph(Module &M, TargetLibraryInfo &TLI); LazyCallGraph(LazyCallGraph &&G); LazyCallGraph &operator=(LazyCallGraph &&RHS); @@ -966,6 +967,22 @@ public: return insertInto(F, N); } + /// Get the sequence of known and defined library functions. + /// + /// These functions, because they are known to LLVM, can have calls + /// introduced out of thin air from arbitrary IR. + ArrayRef<Function *> getLibFunctions() const { + return LibFunctions.getArrayRef(); + } + + /// Test whether a function is a known and defined library function tracked by + /// the call graph. + /// + /// Because these functions are known to LLVM they are specially modeled in + /// the call graph and even when all IR-level references have been removed + /// remain active and reachable. + bool isLibFunction(Function &F) const { return LibFunctions.count(&F); } + ///@{ /// \name Pre-SCC Mutation API /// @@ -1100,6 +1117,11 @@ private: /// These are all of the RefSCCs which have no children. SmallVector<RefSCC *, 4> LeafRefSCCs; + /// Defined functions that are also known library functions which the + /// optimizer can reason about and therefore might introduce calls to out of + /// thin air. + SmallSetVector<Function *, 4> LibFunctions; + /// Helper to insert a new function, with an already looked-up entry in /// the NodeMap. Node &insertInto(Function &F, Node *&MappedN); @@ -1216,8 +1238,8 @@ public: /// /// This just builds the set of entry points to the call graph. The rest is /// built lazily as it is walked. - LazyCallGraph run(Module &M, ModuleAnalysisManager &) { - return LazyCallGraph(M); + LazyCallGraph run(Module &M, ModuleAnalysisManager &AM) { + return LazyCallGraph(M, AM.getResult<TargetLibraryAnalysis>(M)); } }; diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 096df1e421a7..70ce9a870517 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -56,7 +56,8 @@ class Loop; class MDNode; class PHINode; class raw_ostream; -template<class N> class DominatorTreeBase; +template <class N, bool IsPostDom> +class DominatorTreeBase; template<class N, class M> class LoopInfoBase; template<class N, class M> class LoopBase; @@ -663,12 +664,12 @@ public: } /// Create the loop forest using a stable algorithm. - void analyze(const DominatorTreeBase<BlockT> &DomTree); + void analyze(const DominatorTreeBase<BlockT, false> &DomTree); // Debugging void print(raw_ostream &OS) const; - void verify(const DominatorTreeBase<BlockT> &DomTree) const; + void verify(const DominatorTreeBase<BlockT, false> &DomTree) const; }; // Implementation in LoopInfoImpl.h @@ -683,7 +684,7 @@ class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { LoopInfo(const LoopInfo &) = delete; public: LoopInfo() {} - explicit LoopInfo(const DominatorTreeBase<BasicBlock> &DomTree); + explicit LoopInfo(const DominatorTreeBase<BasicBlock, false> &DomTree); LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} LoopInfo &operator=(LoopInfo &&RHS) { diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 372fc8b21745..e9177e68ed77 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -340,10 +340,10 @@ void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth, /// Discover a subloop with the specified backedges such that: All blocks within /// this loop are mapped to this loop or a subloop. And all subloops within this /// loop have their parent loop set to this loop or a subloop. -template<class BlockT, class LoopT> -static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, - LoopInfoBase<BlockT, LoopT> *LI, - const DominatorTreeBase<BlockT> &DomTree) { +template <class BlockT, class LoopT> +static void discoverAndMapSubloop( + LoopT *L, ArrayRef<BlockT *> Backedges, LoopInfoBase<BlockT, LoopT> *LI, + const DomTreeBase<BlockT> &DomTree) { typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; unsigned NumBlocks = 0; @@ -462,10 +462,9 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) { /// /// The Block vectors are inclusive, so step 3 requires loop-depth number of /// insertions per block. -template<class BlockT, class LoopT> -void LoopInfoBase<BlockT, LoopT>:: -analyze(const DominatorTreeBase<BlockT> &DomTree) { - +template <class BlockT, class LoopT> +void LoopInfoBase<BlockT, LoopT>::analyze( + const DomTreeBase<BlockT> &DomTree) { // Postorder traversal of the dominator tree. const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode(); for (auto DomNode : post_order(DomRoot)) { @@ -607,7 +606,7 @@ static void compareLoops(const LoopT *L, const LoopT *OtherL, template <class BlockT, class LoopT> void LoopInfoBase<BlockT, LoopT>::verify( - const DominatorTreeBase<BlockT> &DomTree) const { + const DomTreeBase<BlockT> &DomTree) const { DenseSet<const LoopT*> Loops; for (iterator I = begin(), E = end(); I != E; ++I) { assert(!(*I)->getParentLoop() && "Top-level loop has a parent!"); diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 94ee3b03bb86..17f2e8eaf4a2 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -22,10 +22,8 @@ namespace llvm { /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to /// compute the post-dominator tree. /// -struct PostDominatorTree : public DominatorTreeBase<BasicBlock> { - typedef DominatorTreeBase<BasicBlock> Base; - - PostDominatorTree() : DominatorTreeBase<BasicBlock>(true) {} +struct PostDominatorTree : public PostDomTreeBase<BasicBlock> { + typedef PostDomTreeBase<BasicBlock> Base; /// Handle invalidation explicitly. bool invalidate(Function &F, const PreservedAnalyses &PA, diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index c7accfae78b0..d1b182755cf8 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -237,17 +237,15 @@ struct FoldingSetTrait<SCEVPredicate> : DefaultFoldingSetTrait<SCEVPredicate> { }; /// This class represents an assumption that two SCEV expressions are equal, -/// and this can be checked at run-time. We assume that the left hand side is -/// a SCEVUnknown and the right hand side a constant. +/// and this can be checked at run-time. class SCEVEqualPredicate final : public SCEVPredicate { - /// We assume that LHS == RHS, where LHS is a SCEVUnknown and RHS a - /// constant. - const SCEVUnknown *LHS; - const SCEVConstant *RHS; + /// We assume that LHS == RHS. + const SCEV *LHS; + const SCEV *RHS; public: - SCEVEqualPredicate(const FoldingSetNodeIDRef ID, const SCEVUnknown *LHS, - const SCEVConstant *RHS); + SCEVEqualPredicate(const FoldingSetNodeIDRef ID, const SCEV *LHS, + const SCEV *RHS); /// Implementation of the SCEVPredicate interface bool implies(const SCEVPredicate *N) const override; @@ -256,10 +254,10 @@ public: const SCEV *getExpr() const override; /// Returns the left hand side of the equality. - const SCEVUnknown *getLHS() const { return LHS; } + const SCEV *getLHS() const { return LHS; } /// Returns the right hand side of the equality. - const SCEVConstant *getRHS() const { return RHS; } + const SCEV *getRHS() const { return RHS; } /// Methods for support type inquiry through isa, cast, and dyn_cast: static bool classof(const SCEVPredicate *P) { @@ -1241,6 +1239,14 @@ public: SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end()); return getAddRecExpr(NewOp, L, Flags); } + + /// Checks if \p SymbolicPHI can be rewritten as an AddRecExpr under some + /// Predicates. If successful return these <AddRecExpr, Predicates>; + /// The function is intended to be called from PSCEV (the caller will decide + /// whether to actually add the predicates and carry out the rewrites). + Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI); + /// Returns an expression for a GEP /// /// \p GEP The GEP. The indices contained in the GEP itself are ignored, @@ -1675,8 +1681,7 @@ public: return F.getParent()->getDataLayout(); } - const SCEVPredicate *getEqualPredicate(const SCEVUnknown *LHS, - const SCEVConstant *RHS); + const SCEVPredicate *getEqualPredicate(const SCEV *LHS, const SCEV *RHS); const SCEVPredicate * getWrapPredicate(const SCEVAddRecExpr *AR, @@ -1692,6 +1697,19 @@ public: SmallPtrSetImpl<const SCEVPredicate *> &Preds); private: + /// Similar to createAddRecFromPHI, but with the additional flexibility of + /// suggesting runtime overflow checks in case casts are encountered. + /// If successful, the analysis records that for this loop, \p SymbolicPHI, + /// which is the UnknownSCEV currently representing the PHI, can be rewritten + /// into an AddRec, assuming some predicates; The function then returns the + /// AddRec and the predicates as a pair, and caches this pair in + /// PredicatedSCEVRewrites. + /// If the analysis is not successful, a mapping from the \p SymbolicPHI to + /// itself (with no predicates) is recorded, and a nullptr with an empty + /// predicates vector is returned as a pair. + Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI); + /// Compute the backedge taken count knowing the interval difference, the /// stride and presence of the equality in the comparison. const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride, @@ -1722,6 +1740,12 @@ private: FoldingSet<SCEVPredicate> UniquePreds; BumpPtrAllocator SCEVAllocator; + /// Cache tentative mappings from UnknownSCEVs in a Loop, to a SCEV expression + /// they can be rewritten into under certain predicates. + DenseMap<std::pair<const SCEVUnknown *, const Loop *>, + std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>> + PredicatedSCEVRewrites; + /// The head of a linked list of all SCEVUnknown values that have been /// allocated. This is used by releaseMemory to locate them all and call /// their destructors. diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index dfb525e3de7a..24edd3826a2e 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -155,6 +155,13 @@ public: int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands) const; + /// \brief Estimate the cost of a EXT 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 EXT operation. + int getExtCost(const Instruction *I, const Value *Src) const; + /// \brief Estimate the cost of a function call when lowered. /// /// The contract for this is the same as \c getOperationCost except that it @@ -849,6 +856,7 @@ public: virtual int getOperationCost(unsigned Opcode, Type *Ty, Type *OpTy) = 0; virtual int getGEPCost(Type *PointeeType, const Value *Ptr, ArrayRef<const Value *> Operands) = 0; + virtual int getExtCost(const Instruction *I, const Value *Src) = 0; virtual int getCallCost(FunctionType *FTy, int NumArgs) = 0; virtual int getCallCost(const Function *F, int NumArgs) = 0; virtual int getCallCost(const Function *F, @@ -1022,6 +1030,9 @@ public: ArrayRef<const Value *> Operands) override { return Impl.getGEPCost(PointeeType, Ptr, Operands); } + int getExtCost(const Instruction *I, const Value *Src) override { + return Impl.getExtCost(I, Src); + } int getCallCost(FunctionType *FTy, int NumArgs) override { return Impl.getCallCost(FTy, NumArgs); } diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index 8740ee92eed5..0b07fe9aa232 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -120,6 +120,10 @@ public: return SI.getNumCases(); } + int getExtCost(const Instruction *I, const Value *Src) { + return TTI::TCC_Basic; + } + unsigned getCallCost(FunctionType *FTy, int NumArgs) { assert(FTy && "FunctionType must be provided to this routine."); @@ -728,6 +732,8 @@ public: // nop on most sane targets. if (isa<CmpInst>(CI->getOperand(0))) return TTI::TCC_Free; + if (isa<SExtInst>(CI) || isa<ZExtInst>(CI) || isa<FPExtInst>(CI)) + return static_cast<T *>(this)->getExtCost(CI, Operands.back()); } return static_cast<T *>(this)->getOperationCost( diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index b59fd60e8aed..633107024792 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -155,6 +155,18 @@ public: return BaseT::getGEPCost(PointeeType, Ptr, Operands); } + int getExtCost(const Instruction *I, const Value *Src) { + if (getTLI()->isExtFree(I)) + return TargetTransformInfo::TCC_Free; + + if (isa<ZExtInst>(I) || isa<SExtInst>(I)) + if (const LoadInst *LI = dyn_cast<LoadInst>(Src)) + if (getTLI()->isExtLoad(LI, I, DL)) + return TargetTransformInfo::TCC_Free; + + return TargetTransformInfo::TCC_Basic; + } + unsigned getIntrinsicCost(Intrinsic::ID IID, Type *RetTy, ArrayRef<const Value *> Arguments) { return BaseT::getIntrinsicCost(IID, RetTy, Arguments); diff --git a/include/llvm/CodeGen/MachineDominanceFrontier.h b/include/llvm/CodeGen/MachineDominanceFrontier.h index 370ffbe4862e..6efeefd9a721 100644 --- a/include/llvm/CodeGen/MachineDominanceFrontier.h +++ b/include/llvm/CodeGen/MachineDominanceFrontier.h @@ -23,27 +23,24 @@ class MachineDominanceFrontier : public MachineFunctionPass { ForwardDominanceFrontierBase<MachineBasicBlock> Base; public: - using DomTreeT = DominatorTreeBase<MachineBasicBlock>; - using DomTreeNodeT = DomTreeNodeBase<MachineBasicBlock>; - using DomSetType = DominanceFrontierBase<MachineBasicBlock>::DomSetType; - using iterator = DominanceFrontierBase<MachineBasicBlock>::iterator; - using const_iterator = - DominanceFrontierBase<MachineBasicBlock>::const_iterator; + using DomTreeT = DomTreeBase<MachineBasicBlock>; + using DomTreeNodeT = DomTreeNodeBase<MachineBasicBlock>; + using DomSetType = DominanceFrontierBase<MachineBasicBlock, false>::DomSetType; + using iterator = DominanceFrontierBase<MachineBasicBlock, false>::iterator; + using const_iterator = + DominanceFrontierBase<MachineBasicBlock, false>::const_iterator; - MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; - MachineDominanceFrontier & - operator=(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier(const MachineDominanceFrontier &) = delete; + MachineDominanceFrontier &operator=(const MachineDominanceFrontier &) = delete; - static char ID; + static char ID; - MachineDominanceFrontier(); + MachineDominanceFrontier(); - DominanceFrontierBase<MachineBasicBlock> &getBase() { - return Base; - } + DominanceFrontierBase<MachineBasicBlock, false> &getBase() { return Base; } - inline const std::vector<MachineBasicBlock*> &getRoots() const { - return Base.getRoots(); + inline const std::vector<MachineBasicBlock *> &getRoots() const { + return Base.getRoots(); } MachineBasicBlock *getRoot() const { @@ -98,7 +95,7 @@ public: return Base.compareDomSet(DS1, DS2); } - bool compare(DominanceFrontierBase<MachineBasicBlock> &Other) const { + bool compare(DominanceFrontierBase<MachineBasicBlock, false> &Other) const { return Base.compare(Other); } diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 74a7c3ea04ae..8bf98f606495 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -28,13 +28,15 @@ namespace llvm { -template<> -inline void DominatorTreeBase<MachineBasicBlock>::addRoot(MachineBasicBlock* MBB) { +template <> +inline void DominatorTreeBase<MachineBasicBlock, false>::addRoot( + MachineBasicBlock *MBB) { this->Roots.push_back(MBB); } extern template class DomTreeNodeBase<MachineBasicBlock>; -extern template class DominatorTreeBase<MachineBasicBlock>; +extern template class DominatorTreeBase<MachineBasicBlock, false>; // DomTree +extern template class DominatorTreeBase<MachineBasicBlock, true>; // PostDomTree using MachineDomTreeNode = DomTreeNodeBase<MachineBasicBlock>; @@ -65,7 +67,7 @@ class MachineDominatorTree : public MachineFunctionPass { mutable SmallSet<MachineBasicBlock *, 32> NewBBs; /// The DominatorTreeBase that is used to compute a normal dominator tree - std::unique_ptr<DominatorTreeBase<MachineBasicBlock>> DT; + std::unique_ptr<DomTreeBase<MachineBasicBlock>> DT; /// \brief Apply all the recorded critical edges to the DT. /// This updates the underlying DT information in a way that uses @@ -79,9 +81,8 @@ public: MachineDominatorTree(); - DominatorTreeBase<MachineBasicBlock> &getBase() { - if (!DT) - DT.reset(new DominatorTreeBase<MachineBasicBlock>(false)); + DomTreeBase<MachineBasicBlock> &getBase() { + if (!DT) DT.reset(new DomTreeBase<MachineBasicBlock>()); applySplitCriticalEdges(); return *DT; } diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index 70bdb191ad34..d29d2d85cb0a 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -26,7 +26,7 @@ namespace llvm { /// struct MachinePostDominatorTree : public MachineFunctionPass { private: - DominatorTreeBase<MachineBasicBlock> *DT; + PostDomTreeBase<MachineBasicBlock> *DT; public: static char ID; diff --git a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index 70ccc867cd38..df55e181364c 100644 --- a/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -17,7 +17,6 @@ namespace llvm { namespace codeview { class TypeCollection; -class TypeServerHandler; class TypeVisitorCallbacks; enum VisitorDataSource { @@ -31,11 +30,9 @@ enum VisitorDataSource { Error visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, - VisitorDataSource Source = VDS_BytesPresent, - TypeServerHandler *TS = nullptr); + VisitorDataSource Source = VDS_BytesPresent); Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, - VisitorDataSource Source = VDS_BytesPresent, - TypeServerHandler *TS = nullptr); + VisitorDataSource Source = VDS_BytesPresent); Error visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source = VDS_BytesPresent); @@ -46,12 +43,9 @@ Error visitMemberRecordStream(ArrayRef<uint8_t> FieldList, TypeVisitorCallbacks &Callbacks); Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, - VisitorDataSource Source = VDS_BytesPresent, - TypeServerHandler *TS = nullptr); -Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS = nullptr); -Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS = nullptr); + VisitorDataSource Source = VDS_BytesPresent); +Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks); +Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks); } // end namespace codeview } // end namespace llvm diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h index db944c7057f7..94f104ff772c 100644 --- a/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ b/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -84,7 +84,7 @@ public: Error mapEncodedInteger(uint64_t &Value); Error mapEncodedInteger(APSInt &Value); Error mapStringZ(StringRef &Value); - Error mapGuid(StringRef &Guid); + Error mapGuid(GUID &Guid); Error mapStringZVectorZ(std::vector<StringRef> &Value); diff --git a/include/llvm/DebugInfo/CodeView/Formatters.h b/include/llvm/DebugInfo/CodeView/Formatters.h index 0842c1e373db..278ad02a39cd 100644 --- a/include/llvm/DebugInfo/CodeView/Formatters.h +++ b/include/llvm/DebugInfo/CodeView/Formatters.h @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/FormatVariadic.h" @@ -31,7 +32,7 @@ public: explicit GuidAdapter(ArrayRef<uint8_t> Guid); explicit GuidAdapter(StringRef Guid); - void format(raw_ostream &Stream, StringRef Style) override ; + void format(raw_ostream &Stream, StringRef Style) override; }; } // end namespace detail @@ -60,6 +61,13 @@ public: } }; +template <> struct format_provider<codeview::GUID> { + static void format(const codeview::GUID &V, llvm::raw_ostream &Stream, + StringRef Style) { + Stream << V; + } +}; + } // end namespace llvm #endif // LLVM_DEBUGINFO_CODEVIEW_FORMATTERS_H diff --git a/include/llvm/DebugInfo/CodeView/GUID.h b/include/llvm/DebugInfo/CodeView/GUID.h new file mode 100644 index 000000000000..a055ce9e2e45 --- /dev/null +++ b/include/llvm/DebugInfo/CodeView/GUID.h @@ -0,0 +1,55 @@ +//===- GUID.h ---------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_CODEVIEW_GUID_H +#define LLVM_DEBUGINFO_CODEVIEW_GUID_H + +#include <cstdint> +#include <cstring> + +namespace llvm { +class raw_ostream; + +namespace codeview { + +/// This represents the 'GUID' type from windows.h. +struct GUID { + uint8_t Guid[16]; +}; + +inline bool operator==(const GUID &LHS, const GUID &RHS) { + return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)); +} + +inline bool operator<(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) < 0; +} + +inline bool operator<=(const GUID &LHS, const GUID &RHS) { + return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) <= 0; +} + +inline bool operator>(const GUID &LHS, const GUID &RHS) { + return !(LHS <= RHS); +} + +inline bool operator>=(const GUID &LHS, const GUID &RHS) { + return !(LHS < RHS); +} + +inline bool operator!=(const GUID &LHS, const GUID &RHS) { + return !(LHS == RHS); +} + +raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid); + +} // namespace codeview +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h index cdfc1745cea5..f3086cf3dbb9 100644 --- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -848,7 +848,7 @@ public: : SymbolRecord(SymbolRecordKind::BuildInfoSym), RecordOffset(RecordOffset) {} - uint32_t BuildId; + TypeIndex BuildId; uint32_t RecordOffset; }; diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h index 2efeb1b3cefd..7942c0c0bc21 100644 --- a/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -18,6 +18,7 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/CodeView.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/BinaryStreamArray.h" #include "llvm/Support/Endian.h" @@ -539,15 +540,17 @@ class TypeServer2Record : public TypeRecord { public: TypeServer2Record() = default; explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} - TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name) - : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age), - Name(Name) {} + TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name) + : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) { + assert(GuidStr.size() == 16 && "guid isn't 16 bytes"); + ::memcpy(Guid.Guid, GuidStr.data(), 16); + } - StringRef getGuid() const { return Guid; } + const GUID &getGuid() const { return Guid; } uint32_t getAge() const { return Age; } StringRef getName() const { return Name; } - StringRef Guid; + GUID Guid; uint32_t Age; StringRef Name; }; diff --git a/include/llvm/DebugInfo/CodeView/TypeServerHandler.h b/include/llvm/DebugInfo/CodeView/TypeServerHandler.h deleted file mode 100644 index e96baad9ceae..000000000000 --- a/include/llvm/DebugInfo/CodeView/TypeServerHandler.h +++ /dev/null @@ -1,38 +0,0 @@ -//===- TypeServerHandler.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H - -#include "llvm/Support/Error.h" - -namespace llvm { -namespace codeview { - -class TypeServer2Record; -class TypeVisitorCallbacks; - -class TypeServerHandler { -public: - virtual ~TypeServerHandler() = default; - - /// Handle a TypeServer record. If the implementation returns true - /// the record will not be processed by the top-level visitor. If - /// it returns false, it will be processed. If it returns an Error, - /// then the top-level visitor will fail. - virtual Expected<bool> handle(TypeServer2Record &TS, - TypeVisitorCallbacks &Callbacks) { - return false; - } -}; - -} // end namespace codeview -} // end namespace llvm - -#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERVERHANDLER_H diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h index 3ad2b4e9c92f..d78fab47db66 100644 --- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h +++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h @@ -19,7 +19,6 @@ namespace llvm { namespace codeview { class TypeIndex; -class TypeServerHandler; class TypeTableBuilder; /// \brief Merge one set of type records into another. This method assumes @@ -31,16 +30,13 @@ class TypeTableBuilder; /// type stream, that contains the index of the corresponding type record /// in the destination stream. /// -/// \param Handler (optional) If non-null, an interface that gets invoked -/// to handle type server records. -/// /// \param Types The collection of types to merge in. /// /// \returns Error::success() if the operation succeeded, otherwise an /// appropriate error code. Error mergeTypeRecords(TypeTableBuilder &Dest, SmallVectorImpl<TypeIndex> &SourceToDest, - TypeServerHandler *Handler, const CVTypeArray &Types); + const CVTypeArray &Types); /// \brief Merge one set of id records into another. This method assumes /// that all records are id records, and there are no Type records present. @@ -65,7 +61,7 @@ Error mergeTypeRecords(TypeTableBuilder &Dest, /// appropriate error code. Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, SmallVectorImpl<TypeIndex> &SourceToDest, - const CVTypeArray &Ids); + const CVTypeArray &Ids); /// \brief Merge a unified set of type and id records, splitting them into /// separate output streams. @@ -78,9 +74,6 @@ Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, /// id stream, that contains the index of the corresponding id record /// in the destination stream. /// -/// \param Handler (optional) If non-null, an interface that gets invoked -/// to handle type server records. -/// /// \param IdsAndTypes The collection of id records to merge in. /// /// \returns Error::success() if the operation succeeded, otherwise an @@ -88,8 +81,7 @@ Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types, Error mergeTypeAndIdRecords(TypeTableBuilder &DestIds, TypeTableBuilder &DestTypes, SmallVectorImpl<TypeIndex> &SourceToDest, - TypeServerHandler *Handler, - const CVTypeArray &IdsAndTypes); + const CVTypeArray &IdsAndTypes); } // end namespace codeview } // end namespace llvm diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index ea36ab7ab5b6..056c1b77c65d 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -238,6 +238,34 @@ public: uint8_t getUnitType() const { return UnitType; } + static bool isValidUnitType(uint8_t UnitType) { + return UnitType == dwarf::DW_UT_compile || UnitType == dwarf::DW_UT_type || + UnitType == dwarf::DW_UT_partial || + UnitType == dwarf::DW_UT_skeleton || + UnitType == dwarf::DW_UT_split_compile || + UnitType == dwarf::DW_UT_split_type; + } + + /// \brief Return the number of bytes for the header of a unit of + /// UnitType type. + /// + /// This function must be called with a valid unit type which in + /// DWARF5 is defined as one of the following six types. + static uint32_t getDWARF5HeaderSize(uint8_t UnitType) { + switch (UnitType) { + case dwarf::DW_UT_compile: + case dwarf::DW_UT_partial: + return 12; + case dwarf::DW_UT_skeleton: + case dwarf::DW_UT_split_compile: + return 20; + case dwarf::DW_UT_type: + case dwarf::DW_UT_split_type: + return 24; + } + llvm_unreachable("Invalid UnitType."); + } + uint64_t getBaseAddress() const { return BaseAddr; } void setBaseAddress(uint64_t base_addr) { diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index 9eb5c45faba8..c0291a83ed97 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -21,6 +21,7 @@ class DWARFContext; class DWARFDie; class DWARFUnit; class DWARFAcceleratorTable; +class DWARFDataExtractor; /// A class that verifies DWARF debug information given a DWARF Context. class DWARFVerifier { @@ -30,10 +31,35 @@ class DWARFVerifier { /// can verify each reference points to a valid DIE and not an offset that /// lies between to valid DIEs. std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets; - uint32_t NumDebugInfoErrors = 0; uint32_t NumDebugLineErrors = 0; uint32_t NumAppleNamesErrors = 0; + /// Verifies the header of a unit in the .debug_info section. + /// + /// This function currently checks for: + /// - Unit is in 32-bit DWARF format. The function can be modified to + /// support 64-bit format. + /// - The DWARF version is valid + /// - The unit type is valid (if unit is in version >=5) + /// - The unit doesn't extend beyond .debug_info section + /// - The address size is valid + /// - The offset in the .debug_abbrev section is valid + /// + /// \param DebugInfoData The .debug_info section data + /// \param Offset A reference to the offset start of the unit. The offset will + /// be updated to point to the next unit in .debug_info + /// \param UnitIndex The index of the unit to be verified + /// \param UnitType A reference to the type of the unit + /// \param isUnitDWARF64 A reference to a flag that shows whether the unit is + /// in 64-bit format. + /// + /// \returns true if the header is verified successfully, false otherwise. + bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData, + uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType, + bool &isUnitDWARF64); + + + bool verifyUnitContents(DWARFUnit Unit); /// Verifies the attribute's DWARF attribute and its value. /// /// This function currently checks for: @@ -42,7 +68,11 @@ class DWARFVerifier { /// /// \param Die The DWARF DIE that owns the attribute value /// \param AttrValue The DWARF attribute value to check - void verifyDebugInfoAttribute(const DWARFDie &Die, DWARFAttribute &AttrValue); + /// + /// \returns NumErrors The number of errors occured during verification of + /// attributes' values in a .debug_info section unit + unsigned verifyDebugInfoAttribute(const DWARFDie &Die, + DWARFAttribute &AttrValue); /// Verifies the attribute's DWARF form. /// @@ -53,7 +83,10 @@ class DWARFVerifier { /// /// \param Die The DWARF DIE that owns the attribute value /// \param AttrValue The DWARF attribute value to check - void verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); + /// + /// \returns NumErrors The number of errors occured during verification of + /// attributes' forms in a .debug_info section unit + unsigned verifyDebugInfoForm(const DWARFDie &Die, DWARFAttribute &AttrValue); /// Verifies the all valid references that were found when iterating through /// all of the DIE attributes. @@ -62,7 +95,10 @@ class DWARFVerifier { /// offset matches. This helps to ensure if a DWARF link phase moved things /// around, that it doesn't create invalid references by failing to relocate /// CU relative and absolute references. - void verifyDebugInfoReferences(); + /// + /// \returns NumErrors The number of errors occured during verification of + /// references for the .debug_info section + unsigned verifyDebugInfoReferences(); /// Verify the the DW_AT_stmt_list encoding and value and ensure that no /// compile units that have the same DW_AT_stmt_list value. diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h index 3710eb29e7f9..d37b48540ffa 100644 --- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h +++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h @@ -106,7 +106,7 @@ public: getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; PDB_SymType getSymTag() const override; - PDB_UniqueId getGuid() const override; + codeview::GUID getGuid() const override; int32_t getOffset() const override; int32_t getThisAdjust() const override; int32_t getVirtualBasePointerOffset() const override; diff --git a/include/llvm/DebugInfo/PDB/GenericError.h b/include/llvm/DebugInfo/PDB/GenericError.h index 466cb455651b..03205a986f1a 100644 --- a/include/llvm/DebugInfo/PDB/GenericError.h +++ b/include/llvm/DebugInfo/PDB/GenericError.h @@ -19,6 +19,7 @@ namespace pdb { enum class generic_error_code { invalid_path = 1, dia_sdk_not_present, + type_server_not_found, unspecified, }; diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h index fab086c62c72..eefc36518728 100644 --- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h @@ -118,7 +118,7 @@ public: virtual uint32_t getVirtualTableShapeId() const = 0; virtual PDB_DataKind getDataKind() const = 0; virtual PDB_SymType getSymTag() const = 0; - virtual PDB_UniqueId getGuid() const = 0; + virtual codeview::GUID getGuid() const = 0; virtual int32_t getOffset() const = 0; virtual int32_t getThisAdjust() const = 0; virtual int32_t getVirtualBasePointerOffset() const = 0; diff --git a/include/llvm/DebugInfo/PDB/Native/Formatters.h b/include/llvm/DebugInfo/PDB/Native/Formatters.h index 183f0ad8307e..7d5eab2e2a09 100644 --- a/include/llvm/DebugInfo/PDB/Native/Formatters.h +++ b/include/llvm/DebugInfo/PDB/Native/Formatters.h @@ -23,13 +23,6 @@ break; namespace llvm { -template <> struct format_provider<pdb::PDB_UniqueId> { - static void format(const pdb::PDB_UniqueId &V, llvm::raw_ostream &Stream, - StringRef Style) { - codeview::fmt_guid(V.Guid).format(Stream, Style); - } -}; - template <> struct format_provider<pdb::PdbRaw_ImplVer> { static void format(const pdb::PdbRaw_ImplVer &V, llvm::raw_ostream &Stream, StringRef Style) { diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStream.h b/include/llvm/DebugInfo/PDB/Native/InfoStream.h index 37bf5f3b573c..fb8271cb5ebc 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStream.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStream.h @@ -12,6 +12,7 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h" #include "llvm/DebugInfo/PDB/Native/RawConstants.h" @@ -39,7 +40,7 @@ public: PdbRaw_ImplVer getVersion() const; uint32_t getSignature() const; uint32_t getAge() const; - PDB_UniqueId getGuid() const; + codeview::GUID getGuid() const; uint32_t getNamedStreamMapByteSize() const; PdbRaw_Features getFeatures() const; @@ -71,7 +72,7 @@ private: // Due to the aforementioned limitations with `Signature`, this is a new // signature present on VC70 and higher PDBs which is guaranteed to be // universally unique. - PDB_UniqueId Guid; + codeview::GUID Guid; BinarySubstreamRef SubNamedStreams; diff --git a/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h index 90c28a90d252..c6cb0e221e70 100644 --- a/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h +++ b/include/llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h @@ -37,7 +37,7 @@ public: void setVersion(PdbRaw_ImplVer V); void setSignature(uint32_t S); void setAge(uint32_t A); - void setGuid(PDB_UniqueId G); + void setGuid(codeview::GUID G); void addFeature(PdbRaw_FeatureSig Sig); uint32_t finalize(); @@ -54,7 +54,7 @@ private: PdbRaw_ImplVer Ver; uint32_t Sig; uint32_t Age; - PDB_UniqueId Guid; + codeview::GUID Guid; NamedStreamMap &NamedStreams; }; diff --git a/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h index ddb7f811da38..587c7ff2b092 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeExeSymbol.h @@ -27,7 +27,7 @@ public: uint32_t getAge() const override; std::string getSymbolsFileName() const override; - PDB_UniqueId getGuid() const override; + codeview::GUID getGuid() const override; bool hasCTypes() const override; bool hasPrivateSymbols() const override; diff --git a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h index 66a9eae28e23..2c6548dcce21 100644 --- a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h +++ b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h @@ -111,7 +111,7 @@ public: getVirtualBaseTableType() const override; PDB_DataKind getDataKind() const override; PDB_SymType getSymTag() const override; - PDB_UniqueId getGuid() const override; + codeview::GUID getGuid() const override; int32_t getOffset() const override; int32_t getThisAdjust() const override; int32_t getVirtualBasePointerOffset() const override; diff --git a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h b/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h deleted file mode 100644 index 196ba4d6ffbd..000000000000 --- a/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- PDBTypeServerHandler.h -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEBUGINFO_PDB_PDBTYPESERVERHANDLER_H -#define LLVM_DEBUGINFO_PDB_PDBTYPESERVERHANDLER_H - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringSet.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" -#include "llvm/DebugInfo/PDB/Native/NativeSession.h" -#include "llvm/DebugInfo/PDB/PDBTypes.h" - -#include <memory> -#include <string> - -namespace llvm { -namespace pdb { -class NativeSession; - -class PDBTypeServerHandler : public codeview::TypeServerHandler { -public: - PDBTypeServerHandler(bool RevisitAlways = false); - - void addSearchPath(StringRef Path); - Expected<bool> handle(codeview::TypeServer2Record &TS, - codeview::TypeVisitorCallbacks &Callbacks) override; - -private: - Expected<bool> handleInternal(PDBFile &File, - codeview::TypeVisitorCallbacks &Callbacks); - - bool RevisitAlways; - std::unique_ptr<NativeSession> Session; - StringSet<> SearchPaths; -}; -} -} - -#endif diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h index a3cdd3f09a44..b6321cbf45a8 100644 --- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h +++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H #define LLVM_DEBUGINFO_PDB_RAW_RAWTYPES_H +#include "llvm/DebugInfo/CodeView/GUID.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/Support/Endian.h" @@ -268,17 +269,6 @@ struct PublicsStreamHeader { support::ulittle32_t NumSections; }; -/// Defines a 128-bit unique identifier. This maps to a GUID on Windows, but -/// is abstracted here for the purposes of non-Windows platforms that don't have -/// the GUID structure defined. -struct PDB_UniqueId { - uint8_t Guid[16]; -}; - -inline bool operator==(const PDB_UniqueId &LHS, const PDB_UniqueId &RHS) { - return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)); -} - // The header preceeding the global TPI stream. // This corresponds to `HDR` in PDB/dbi/tpi.h. struct TpiStreamHeader { @@ -312,7 +302,7 @@ struct InfoStreamHeader { support::ulittle32_t Version; support::ulittle32_t Signature; support::ulittle32_t Age; - PDB_UniqueId Guid; + codeview::GUID Guid; }; /// The header preceeding the /names stream. diff --git a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h index 156abb59a6be..c1edec7a26fe 100644 --- a/include/llvm/DebugInfo/PDB/Native/TpiHashing.h +++ b/include/llvm/DebugInfo/PDB/Native/TpiHashing.h @@ -10,84 +10,13 @@ #ifndef LLVM_DEBUGINFO_PDB_TPIHASHING_H #define LLVM_DEBUGINFO_PDB_TPIHASHING_H -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" -#include "llvm/DebugInfo/PDB/Native/RawError.h" -#include "llvm/Support/BinaryStreamArray.h" -#include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" -#include <cstdint> -#include <string> namespace llvm { namespace pdb { -class TpiHashUpdater : public codeview::TypeVisitorCallbacks { -public: - TpiHashUpdater() = default; - -#define TYPE_RECORD(EnumName, EnumVal, Name) \ - virtual Error visitKnownRecord(codeview::CVType &CVR, \ - codeview::Name##Record &Record) override { \ - visitKnownRecordImpl(CVR, Record); \ - return Error::success(); \ - } -#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#define MEMBER_RECORD(EnumName, EnumVal, Name) -#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" - -private: - template <typename RecordKind> - void visitKnownRecordImpl(codeview::CVType &CVR, RecordKind &Record) { - CVR.Hash = 0; - } - - void visitKnownRecordImpl(codeview::CVType &CVR, - codeview::UdtSourceLineRecord &Rec); - void visitKnownRecordImpl(codeview::CVType &CVR, - codeview::UdtModSourceLineRecord &Rec); - void visitKnownRecordImpl(codeview::CVType &CVR, codeview::ClassRecord &Rec); - void visitKnownRecordImpl(codeview::CVType &CVR, codeview::EnumRecord &Rec); - void visitKnownRecordImpl(codeview::CVType &CVR, codeview::UnionRecord &Rec); -}; - -class TpiHashVerifier : public codeview::TypeVisitorCallbacks { -public: - TpiHashVerifier(FixedStreamArray<support::ulittle32_t> &HashValues, - uint32_t NumHashBuckets) - : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {} - - Error visitKnownRecord(codeview::CVType &CVR, - codeview::UdtSourceLineRecord &Rec) override; - Error visitKnownRecord(codeview::CVType &CVR, - codeview::UdtModSourceLineRecord &Rec) override; - Error visitKnownRecord(codeview::CVType &CVR, - codeview::ClassRecord &Rec) override; - Error visitKnownRecord(codeview::CVType &CVR, - codeview::EnumRecord &Rec) override; - Error visitKnownRecord(codeview::CVType &CVR, - codeview::UnionRecord &Rec) override; - Error visitTypeBegin(codeview::CVType &CVR) override; - -private: - Error verifySourceLine(codeview::TypeIndex TI); - - Error errorInvalidHash() { - return make_error<RawError>( - raw_error_code::invalid_tpi_hash, - "Type index is 0x" + - utohexstr(codeview::TypeIndex::FirstNonSimpleIndex + Index)); - } - - FixedStreamArray<support::ulittle32_t> HashValues; - codeview::CVType RawRecord; - uint32_t NumHashBuckets; - uint32_t Index = -1; -}; +Expected<uint32_t> hashTypeRecord(const llvm::codeview::CVType &Type); } // end namespace pdb } // end namespace llvm diff --git a/include/llvm/DebugInfo/PDB/PDBExtras.h b/include/llvm/DebugInfo/PDB/PDBExtras.h index 3a38f21b94c8..778121c8eb79 100644 --- a/include/llvm/DebugInfo/PDB/PDBExtras.h +++ b/include/llvm/DebugInfo/PDB/PDBExtras.h @@ -32,7 +32,6 @@ raw_ostream &operator<<(raw_ostream &OS, const PDB_Checksum &Checksum); raw_ostream &operator<<(raw_ostream &OS, const PDB_Lang &Lang); raw_ostream &operator<<(raw_ostream &OS, const PDB_SymType &Tag); raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access); -raw_ostream &operator<<(raw_ostream &OS, const PDB_UniqueId &Guid); raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type); raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine); diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index c1acca386820..27b5457fc8ff 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -22,6 +22,7 @@ #include "llvm/ExecutionEngine/JITSymbol.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/ExecutionEngine/Orc/LambdaResolver.h" +#include "llvm/ExecutionEngine/Orc/OrcError.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Constant.h" @@ -289,21 +290,21 @@ public: // FIXME: We should track and free associated resources (unused compile // callbacks, uncompiled IR, and no-longer-needed/reachable function // implementations). - // FIXME: Return Error once the JIT APIs are Errorized. - bool updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) { + Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) { //Find out which logical dylib contains our symbol auto LDI = LogicalDylibs.begin(); for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) { - if (auto LMResources = LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) { + if (auto LMResources = + LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) { Module &SrcM = LMResources->SourceModule->getResource(); std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout()); - if (auto EC = LMResources->StubsMgr->updatePointer(CalledFnName, FnBodyAddr)) - return false; - else - return true; + if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName, + FnBodyAddr)) + return Err; + return Error::success(); } } - return false; + return make_error<JITSymbolNotFound>(FuncName); } private: @@ -363,11 +364,8 @@ private: }); } - auto EC = LD.StubsMgr->createStubs(StubInits); - (void)EC; - // FIXME: This should be propagated back to the user. Stub creation may - // fail for remote JITs. - assert(!EC && "Error generating stubs"); + if (auto Err = LD.StubsMgr->createStubs(StubInits)) + return Err; } // If this module doesn't contain any globals, aliases, or module flags then diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index a9778514b9f1..0c1862c5c3ea 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -135,12 +135,13 @@ public: virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); -private: +protected: struct EHFrame { uint8_t *Addr; size_t Size; }; - std::vector<EHFrame> EHFrames; + typedef std::vector<EHFrame> EHFrameInfos; + EHFrameInfos EHFrames; }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 801e88aba4d1..850964afc307 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -143,11 +143,15 @@ namespace CallingConv { /// System V ABI, used on most non-Windows systems. X86_64_SysV = 78, - /// \brief The C convention as implemented on Windows/x86-64. This - /// convention differs from the more common \c X86_64_SysV convention - /// in a number of ways, most notably in that XMM registers used to pass - /// arguments are shadowed by GPRs, and vice versa. - X86_64_Win64 = 79, + /// \brief The C convention as implemented on Windows/x86-64 and + /// AArch64. This convention differs from the more common + /// \c X86_64_SysV convention in a number of ways, most notably in + /// that XMM registers used to pass arguments are shadowed by GPRs, + /// and vice versa. + /// On AArch64, this is identical to the normal C (AAPCS) calling + /// convention for normal functions, but floats are passed in integer + /// registers to variadic functions. + Win64 = 79, /// \brief MSVC calling convention that passes vectors and vector aggregates /// in SSE registers. diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 2e72c41ccee3..0094fd54992a 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -598,6 +598,10 @@ public: /// specified element in the low bits of a uint64_t. uint64_t getElementAsInteger(unsigned i) const; + /// If this is a sequential container of integers (of any size), return the + /// specified element as an APInt. + APInt getElementAsAPInt(unsigned i) const; + /// If this is a sequential container of floating point type, return the /// specified element as an APFloat. APFloat getElementAsAPFloat(unsigned i) const; @@ -761,6 +765,10 @@ public: /// i32/i64/float/double) and must be a ConstantFP or ConstantInt. static Constant *getSplat(unsigned NumElts, Constant *Elt); + /// Returns true if this is a splat constant, meaning that all elements have + /// the same value. + bool isSplat() const; + /// If this is a splat constant, meaning that all of the elements have the /// same value, return that value. Otherwise return NULL. Constant *getSplatValue() const; diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 8e6bb4baccaf..6a14f783005d 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -674,32 +674,37 @@ namespace llvm { /// Create a descriptor for an imported module. /// \param Context The scope this module is imported into - /// \param NS The namespace being imported here - /// \param Line Line number + /// \param NS The namespace being imported here. + /// \param File File where the declaration is located. + /// \param Line Line number of the declaration. DIImportedEntity *createImportedModule(DIScope *Context, DINamespace *NS, - unsigned Line); + DIFile *File, unsigned Line); /// Create a descriptor for an imported module. - /// \param Context The scope this module is imported into - /// \param NS An aliased namespace - /// \param Line Line number + /// \param Context The scope this module is imported into. + /// \param NS An aliased namespace. + /// \param File File where the declaration is located. + /// \param Line Line number of the declaration. DIImportedEntity *createImportedModule(DIScope *Context, - DIImportedEntity *NS, unsigned Line); + DIImportedEntity *NS, DIFile *File, + unsigned Line); /// Create a descriptor for an imported module. - /// \param Context The scope this module is imported into - /// \param M The module being imported here - /// \param Line Line number + /// \param Context The scope this module is imported into. + /// \param M The module being imported here + /// \param File File where the declaration is located. + /// \param Line Line number of the declaration. DIImportedEntity *createImportedModule(DIScope *Context, DIModule *M, - unsigned Line); + DIFile *File, unsigned Line); /// Create a descriptor for an imported function. - /// \param Context The scope this module is imported into - /// \param Decl The declaration (or definition) of a function, type, or - /// variable - /// \param Line Line number + /// \param Context The scope this module is imported into. + /// \param Decl The declaration (or definition) of a function, type, or + /// variable. + /// \param File File where the declaration is located. + /// \param Line Line number of the declaration. DIImportedEntity *createImportedDeclaration(DIScope *Context, DINode *Decl, - unsigned Line, + DIFile *File, unsigned Line, StringRef Name = ""); /// Insert a new llvm.dbg.declare intrinsic call. diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index 9374fe4fae76..678a43ae7926 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -435,10 +435,10 @@ public: /// Return the raw underlying file. /// - /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file - /// (it\em is the file). If \c this is an \a DIFile, we need to return \c - /// this. Otherwise, return the first operand, which is where all other - /// subclasses store their file pointer. + /// A \a DIFile is a \a DIScope, but it doesn't point at a separate file (it + /// \em is the file). If \c this is an \a DIFile, we need to return \c this. + /// Otherwise, return the first operand, which is where all other subclasses + /// store their file pointer. Metadata *getRawFile() const { return isa<DIFile>(this) ? const_cast<DIScope *>(this) : static_cast<Metadata *>(getOperand(0)); @@ -2551,32 +2551,32 @@ class DIImportedEntity : public DINode { static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, DIScope *Scope, DINodeRef Entity, - unsigned Line, StringRef Name, + DIFile *File, unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Tag, Scope, Entity, Line, + return getImpl(Context, Tag, Scope, Entity, File, Line, getCanonicalMDString(Context, Name), Storage, ShouldCreate); } static DIImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, Metadata *Entity, - unsigned Line, MDString *Name, - StorageType Storage, + Metadata *File, unsigned Line, + MDString *Name, StorageType Storage, bool ShouldCreate = true); TempDIImportedEntity cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getEntity(), - getLine(), getName()); + getFile(), getLine(), getName()); } public: DEFINE_MDNODE_GET(DIImportedEntity, (unsigned Tag, DIScope *Scope, DINodeRef Entity, - unsigned Line, StringRef Name = ""), - (Tag, Scope, Entity, Line, Name)) + DIFile *File, unsigned Line, StringRef Name = ""), + (Tag, Scope, Entity, File, Line, Name)) DEFINE_MDNODE_GET(DIImportedEntity, (unsigned Tag, Metadata *Scope, Metadata *Entity, - unsigned Line, MDString *Name), - (Tag, Scope, Entity, Line, Name)) + Metadata *File, unsigned Line, MDString *Name), + (Tag, Scope, Entity, File, Line, Name)) TempDIImportedEntity clone() const { return cloneImpl(); } @@ -2584,10 +2584,12 @@ public: DIScope *getScope() const { return cast_or_null<DIScope>(getRawScope()); } DINodeRef getEntity() const { return DINodeRef(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } + DIFile *getFile() const { return cast_or_null<DIFile>(getRawFile()); } Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawEntity() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } + Metadata *getRawFile() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == DIImportedEntityKind; diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e10d14c19793..5b21a2c83e4a 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -34,22 +34,31 @@ class Module; class raw_ostream; extern template class DomTreeNodeBase<BasicBlock>; -extern template class DominatorTreeBase<BasicBlock>; +extern template class DominatorTreeBase<BasicBlock, false>; // DomTree +extern template class DominatorTreeBase<BasicBlock, true>; // PostDomTree namespace DomTreeBuilder { -extern template void Calculate<Function, BasicBlock *>( - DominatorTreeBaseByGraphTraits<GraphTraits<BasicBlock *>> &DT, Function &F); - -extern template void Calculate<Function, Inverse<BasicBlock *>>( - DominatorTreeBaseByGraphTraits<GraphTraits<Inverse<BasicBlock *>>> &DT, - Function &F); - -extern template bool Verify<BasicBlock *>( - const DominatorTreeBaseByGraphTraits<GraphTraits<BasicBlock *>> &DT); - -extern template bool Verify<Inverse<BasicBlock *>>( - const DominatorTreeBaseByGraphTraits<GraphTraits<Inverse<BasicBlock *>>> - &DT); +using BBDomTree = DomTreeBase<BasicBlock>; +using BBPostDomTree = PostDomTreeBase<BasicBlock>; + +extern template void Calculate<BBDomTree, Function>(BBDomTree &DT, Function &F); +extern template void Calculate<BBPostDomTree, Function>(BBPostDomTree &DT, + Function &F); + +extern template void InsertEdge<BBDomTree>(BBDomTree &DT, BasicBlock *From, + BasicBlock *To); +extern template void InsertEdge<BBPostDomTree>(BBPostDomTree &DT, + BasicBlock *From, + BasicBlock *To); + +extern template void DeleteEdge<BBDomTree>(BBDomTree &DT, BasicBlock *From, + BasicBlock *To); +extern template void DeleteEdge<BBPostDomTree>(BBPostDomTree &DT, + BasicBlock *From, + BasicBlock *To); + +extern template bool Verify<BBDomTree>(const BBDomTree &DT); +extern template bool Verify<BBPostDomTree>(const BBPostDomTree &DT); } // namespace DomTreeBuilder using DomTreeNode = DomTreeNodeBase<BasicBlock>; @@ -122,14 +131,12 @@ template <> struct DenseMapInfo<BasicBlockEdge> { /// the dominator tree is initially constructed may still exist in the tree, /// even if the tree is properly updated. Calling code should not rely on the /// preceding statements; this is stated only to assist human understanding. -class DominatorTree : public DominatorTreeBase<BasicBlock> { -public: - using Base = DominatorTreeBase<BasicBlock>; +class DominatorTree : public DominatorTreeBase<BasicBlock, false> { + public: + using Base = DominatorTreeBase<BasicBlock, false>; - DominatorTree() : DominatorTreeBase<BasicBlock>(false) {} - explicit DominatorTree(Function &F) : DominatorTreeBase<BasicBlock>(false) { - recalculate(F); - } + DominatorTree() = default; + explicit DominatorTree(Function &F) { recalculate(F); } /// Handle invalidation explicitly. bool invalidate(Function &F, const PreservedAnalyses &PA, diff --git a/include/llvm/IR/IntrinsicsHexagon.td b/include/llvm/IR/IntrinsicsHexagon.td index 8ac56e03be6a..098245344725 100644 --- a/include/llvm/IR/IntrinsicsHexagon.td +++ b/include/llvm/IR/IntrinsicsHexagon.td @@ -32,16 +32,6 @@ class Hexagon_qi_mem_Intrinsic<string GCCIntSuffix> : Hexagon_Intrinsic<GCCIntSuffix, [llvm_i1_ty], [llvm_ptr_ty], [IntrNoMem]>; - -// -// DEF_FUNCTION_TYPE_1(void_ftype_SI,BT_VOID,BT_INT) -> -// Hexagon_void_si_Intrinsic<string GCCIntSuffix> -// -class Hexagon_void_si_Intrinsic<string GCCIntSuffix> - : Hexagon_Intrinsic<GCCIntSuffix, - [], [llvm_ptr_ty], - []>; - // // DEF_FUNCTION_TYPE_1(HI_ftype_SI,BT_I16,BT_INT) -> // Hexagon_hi_si_Intrinsic<string GCCIntSuffix> @@ -4959,11 +4949,25 @@ Hexagon_di_di_Intrinsic<"HEXAGON_S2_interleave">; // def int_hexagon_S2_deinterleave : Hexagon_di_di_Intrinsic<"HEXAGON_S2_deinterleave">; + // // BUILTIN_INFO(HEXAGON.dcfetch_A,v_ftype_DI*,1) // def int_hexagon_prefetch : -Hexagon_void_si_Intrinsic<"HEXAGON_prefetch">; +Hexagon_Intrinsic<"HEXAGON_prefetch", [], [llvm_ptr_ty], []>; +def int_hexagon_Y2_dccleana : +Hexagon_Intrinsic<"HEXAGON_Y2_dccleana", [], [llvm_ptr_ty], []>; +def int_hexagon_Y2_dccleaninva : +Hexagon_Intrinsic<"HEXAGON_Y2_dccleaninva", [], [llvm_ptr_ty], []>; +def int_hexagon_Y2_dcinva : +Hexagon_Intrinsic<"HEXAGON_Y2_dcinva", [], [llvm_ptr_ty], []>; +def int_hexagon_Y2_dczeroa : +Hexagon_Intrinsic<"HEXAGON_Y2_dczeroa", [], [llvm_ptr_ty], + [IntrWriteMem, IntrArgMemOnly, IntrHasSideEffects]>; +def int_hexagon_Y4_l2fetch : +Hexagon_Intrinsic<"HEXAGON_Y4_l2fetch", [], [llvm_ptr_ty, llvm_i32_ty], []>; +def int_hexagon_Y5_l2fetch : +Hexagon_Intrinsic<"HEXAGON_Y5_l2fetch", [], [llvm_ptr_ty, llvm_i64_ty], []>; def llvm_ptr32_ty : LLVMPointerType<llvm_i32_ty>; def llvm_ptr64_ty : LLVMPointerType<llvm_i64_ty>; diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td index 9be37d3645b2..98065bc51d99 100644 --- a/include/llvm/IR/IntrinsicsSystemZ.td +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -373,6 +373,49 @@ let TargetPrefix = "s390" in { def int_s390_vfidb : Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; + + // Instructions from the Vector Enhancements Facility 1 + def int_s390_vbperm : SystemZBinaryConv<"vbperm", llvm_v2i64_ty, + llvm_v16i8_ty>; + + def int_s390_vmslg : GCCBuiltin<"__builtin_s390_vmslg">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_v16i8_ty, + llvm_i32_ty], [IntrNoMem]>; + + def int_s390_vfmaxdb : Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_s390_vfmindb : Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_s390_vfmaxsb : Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_s390_vfminsb : Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_s390_vfcesbs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v4f32_ty>; + def int_s390_vfchsbs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v4f32_ty>; + def int_s390_vfchesbs : SystemZBinaryConvCC<llvm_v4i32_ty, llvm_v4f32_ty>; + + def int_s390_vftcisb : SystemZBinaryConvIntCC<llvm_v4i32_ty, llvm_v4f32_ty>; + + def int_s390_vfisb : Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + + // Instructions from the Vector Packed Decimal Facility + def int_s390_vlrl : GCCBuiltin<"__builtin_s390_vlrl">, + Intrinsic<[llvm_v16i8_ty], [llvm_i32_ty, llvm_ptr_ty], + [IntrReadMem, IntrArgMemOnly]>; + + def int_s390_vstrl : GCCBuiltin<"__builtin_s390_vstrl">, + Intrinsic<[], [llvm_v16i8_ty, llvm_i32_ty, llvm_ptr_ty], + // In fact write-only but there's no property + // for that. + [IntrArgMemOnly]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/MC/LaneBitmask.h b/include/llvm/MC/LaneBitmask.h index 5ca06d1148e2..73b987b074db 100644 --- a/include/llvm/MC/LaneBitmask.h +++ b/include/llvm/MC/LaneBitmask.h @@ -75,6 +75,9 @@ namespace llvm { static LaneBitmask getNone() { return LaneBitmask(0); } static LaneBitmask getAll() { return ~LaneBitmask(0); } + static LaneBitmask getLane(unsigned Lane) { + return LaneBitmask(Type(1) << Lane); + } private: Type Mask = 0; diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index b493ca0b0ea7..b83086c327f2 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -69,7 +69,7 @@ class MCFixup { /// an instruction or an assembler directive. const MCExpr *Value; - /// The byte index of start of the relocation inside the encoded instruction. + /// The byte index of start of the relocation inside the MCFragment. uint32_t Offset; /// The target dependent kind of fixup item this is. The kind is used to diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 340d8253b8c9..9150a8b5c80a 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -209,6 +209,15 @@ public: /// well. unsigned getNumOperands() const { return NumOperands; } + using const_opInfo_iterator = const MCOperandInfo *; + + const_opInfo_iterator opInfo_begin() const { return OpInfo; } + const_opInfo_iterator opInfo_end() const { return OpInfo + NumOperands; } + + iterator_range<const_opInfo_iterator> operands() const { + return make_range(opInfo_begin(), opInfo_end()); + } + /// \brief Return the number of MachineOperands that are register /// definitions. Register definitions always occur at the start of the /// machine operand list. This is the number of "outs" in the .td file, diff --git a/include/llvm/Object/COFFImportFile.h b/include/llvm/Object/COFFImportFile.h index 060f965233e1..8e215b565fc4 100644 --- a/include/llvm/Object/COFFImportFile.h +++ b/include/llvm/Object/COFFImportFile.h @@ -95,7 +95,7 @@ struct COFFShortExport { } }; -std::error_code writeImportLibrary(StringRef DLLName, +std::error_code writeImportLibrary(StringRef ImportName, StringRef Path, ArrayRef<COFFShortExport> Exports, COFF::MachineTypes Machine); diff --git a/include/llvm/Object/COFFModuleDefinition.h b/include/llvm/Object/COFFModuleDefinition.h index a0e8eacdb7a3..be139a2833b0 100644 --- a/include/llvm/Object/COFFModuleDefinition.h +++ b/include/llvm/Object/COFFModuleDefinition.h @@ -16,7 +16,6 @@ // //===----------------------------------------------------------------------===// - #ifndef LLVM_OBJECT_COFF_MODULE_DEFINITION_H #define LLVM_OBJECT_COFF_MODULE_DEFINITION_H @@ -29,6 +28,7 @@ namespace object { struct COFFModuleDefinition { std::vector<COFFShortExport> Exports; std::string OutputFile; + std::string ImportName; uint64_t ImageBase = 0; uint64_t StackReserve = 0; uint64_t StackCommit = 0; @@ -40,8 +40,12 @@ struct COFFModuleDefinition { uint32_t MinorOSVersion = 0; }; +// mingw and wine def files do not mangle _ for x86 which +// is a consequence of legacy binutils' dlltool functionality. +// This MingwDef flag should be removed once mingw stops this pratice. Expected<COFFModuleDefinition> -parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine); +parseCOFFModuleDefinition(MemoryBufferRef MB, COFF::MachineTypes Machine, + bool MingwDef = false); } // End namespace object. } // End namespace llvm. diff --git a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h index 6746fd60b6cb..88a5668f0a14 100644 --- a/include/llvm/ObjectYAML/CodeViewYAMLTypes.h +++ b/include/llvm/ObjectYAML/CodeViewYAMLTypes.h @@ -60,6 +60,8 @@ ArrayRef<uint8_t> toDebugT(ArrayRef<LeafRecord>, BumpPtrAllocator &Alloc); } // end namespace llvm +LLVM_YAML_DECLARE_SCALAR_TRAITS(codeview::GUID, true) + LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::LeafRecord) LLVM_YAML_DECLARE_MAPPING_TRAITS(CodeViewYAML::MemberRecord) diff --git a/include/llvm/Support/AArch64TargetParser.def b/include/llvm/Support/AArch64TargetParser.def index 8eccebcd932a..09f9602a24d9 100644 --- a/include/llvm/Support/AArch64TargetParser.def +++ b/include/llvm/Support/AArch64TargetParser.def @@ -43,8 +43,9 @@ AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") -AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") -AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") +AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve") #undef AARCH64_ARCH_EXT_NAME #ifndef AARCH64_CPU_NAME diff --git a/include/llvm/Support/BinaryItemStream.h b/include/llvm/Support/BinaryItemStream.h index f4b319217819..fe7e6caeaafb 100644 --- a/include/llvm/Support/BinaryItemStream.h +++ b/include/llvm/Support/BinaryItemStream.h @@ -62,32 +62,45 @@ public: return Error::success(); } - void setItems(ArrayRef<T> ItemArray) { Items = ItemArray; } + void setItems(ArrayRef<T> ItemArray) { + Items = ItemArray; + computeItemOffsets(); + } uint32_t getLength() override { - uint32_t Size = 0; - for (const auto &Item : Items) - Size += Traits::length(Item); - return Size; + return ItemEndOffsets.empty() ? 0 : ItemEndOffsets.back(); } private: - Expected<uint32_t> translateOffsetIndex(uint32_t Offset) const { + void computeItemOffsets() { + ItemEndOffsets.clear(); + ItemEndOffsets.reserve(Items.size()); uint32_t CurrentOffset = 0; - uint32_t CurrentIndex = 0; for (const auto &Item : Items) { - if (CurrentOffset >= Offset) - break; - CurrentOffset += Traits::length(Item); - ++CurrentIndex; + uint32_t Len = Traits::length(Item); + assert(Len > 0 && "no empty items"); + CurrentOffset += Len; + ItemEndOffsets.push_back(CurrentOffset); } - if (CurrentOffset != Offset) + } + + Expected<uint32_t> translateOffsetIndex(uint32_t Offset) { + // Make sure the offset is somewhere in our items array. + if (Offset >= getLength()) return make_error<BinaryStreamError>(stream_error_code::stream_too_short); - return CurrentIndex; + ++Offset; + auto Iter = + std::lower_bound(ItemEndOffsets.begin(), ItemEndOffsets.end(), Offset); + size_t Idx = std::distance(ItemEndOffsets.begin(), Iter); + assert(Idx < Items.size() && "binary search for offset failed"); + return Idx; } llvm::support::endianness Endian; ArrayRef<T> Items; + + // Sorted vector of offsets to accelerate lookup. + std::vector<uint32_t> ItemEndOffsets; }; } // end namespace llvm diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index 017b4973f1ff..bcbd2bec5722 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -125,30 +125,39 @@ inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) { return format_object<Ts...>(Fmt, Vals...); } -/// This is a helper class used for left_justify() and right_justify(). +/// This is a helper class for left_justify, right_justify, and center_justify. class FormattedString { +public: + enum Justification { JustifyNone, JustifyLeft, JustifyRight, JustifyCenter }; + FormattedString(StringRef S, unsigned W, Justification J) + : Str(S), Width(W), Justify(J) {} + +private: StringRef Str; unsigned Width; - bool RightJustify; + Justification Justify; friend class raw_ostream; - -public: - FormattedString(StringRef S, unsigned W, bool R) - : Str(S), Width(W), RightJustify(R) { } }; /// left_justify - append spaces after string so total output is /// \p Width characters. If \p Str is larger that \p Width, full string /// is written with no padding. inline FormattedString left_justify(StringRef Str, unsigned Width) { - return FormattedString(Str, Width, false); + return FormattedString(Str, Width, FormattedString::JustifyLeft); } /// right_justify - add spaces before string so total output is /// \p Width characters. If \p Str is larger that \p Width, full string /// is written with no padding. inline FormattedString right_justify(StringRef Str, unsigned Width) { - return FormattedString(Str, Width, true); + return FormattedString(Str, Width, FormattedString::JustifyRight); +} + +/// center_justify - add spaces before and after string so total output is +/// \p Width characters. If \p Str is larger that \p Width, full string +/// is written with no padding. +inline FormattedString center_justify(StringRef Str, unsigned Width) { + return FormattedString(Str, Width, FormattedString::JustifyCenter); } /// This is a helper class used for format_hex() and format_decimal(). diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index 394a45387d8a..706320fed9a7 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -41,27 +41,21 @@ namespace llvm { -template <class NodeT> class DominatorTreeBase; +template <typename NodeT, bool IsPostDom> +class DominatorTreeBase; -namespace detail { - -template <typename GT> struct DominatorTreeBaseTraits { - static_assert(std::is_pointer<typename GT::NodeRef>::value, - "Currently NodeRef must be a pointer type."); - using type = DominatorTreeBase< - typename std::remove_pointer<typename GT::NodeRef>::type>; -}; - -} // end namespace detail - -template <typename GT> -using DominatorTreeBaseByGraphTraits = - typename detail::DominatorTreeBaseTraits<GT>::type; +namespace DomTreeBuilder { +template <class DomTreeT> +struct SemiNCAInfo; +} // namespace DomTreeBuilder /// \brief Base class for the actual dominator tree node. template <class NodeT> class DomTreeNodeBase { friend struct PostDominatorTree; - template <class N> friend class DominatorTreeBase; + friend class DominatorTreeBase<NodeT, false>; + friend class DominatorTreeBase<NodeT, true>; + friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, false>>; + friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase<NodeT, true>>; NodeT *TheBB; DomTreeNodeBase *IDom; @@ -192,58 +186,69 @@ void PrintDomTree(const DomTreeNodeBase<NodeT> *N, raw_ostream &O, } namespace DomTreeBuilder { -template <class NodeT> -struct SemiNCAInfo; +// The routines below are provided in a separate header but referenced here. +template <typename DomTreeT, typename FuncT> +void Calculate(DomTreeT &DT, FuncT &F); + +template <class DomTreeT> +void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, + typename DomTreeT::NodePtr To); -// The calculate routine is provided in a separate header but referenced here. -template <class FuncT, class N> -void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<N>> &DT, FuncT &F); +template <class DomTreeT> +void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, + typename DomTreeT::NodePtr To); -// The verify function is provided in a separate header but referenced here. -template <class N> -bool Verify(const DominatorTreeBaseByGraphTraits<GraphTraits<N>> &DT); +template <typename DomTreeT> +bool Verify(const DomTreeT &DT); } // namespace DomTreeBuilder /// \brief Core dominator tree base class. /// /// This class is a generic template over graph nodes. It is instantiated for /// various graphs in the LLVM IR or in the code generator. -template <class NodeT> class DominatorTreeBase { +template <typename NodeT, bool IsPostDom> +class DominatorTreeBase { protected: std::vector<NodeT *> Roots; - bool IsPostDominators; using DomTreeNodeMapType = DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>>; DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase<NodeT> *RootNode; + using ParentPtr = decltype(std::declval<NodeT *>()->getParent()); + ParentPtr Parent = nullptr; mutable bool DFSInfoValid = false; mutable unsigned int SlowQueries = 0; - friend struct DomTreeBuilder::SemiNCAInfo<NodeT>; - using SNCAInfoTy = DomTreeBuilder::SemiNCAInfo<NodeT>; + friend struct DomTreeBuilder::SemiNCAInfo<DominatorTreeBase>; public: - explicit DominatorTreeBase(bool isPostDom) : IsPostDominators(isPostDom) {} + static_assert(std::is_pointer<typename GraphTraits<NodeT *>::NodeRef>::value, + "Currently DominatorTreeBase supports only pointer nodes"); + using NodeType = NodeT; + using NodePtr = NodeT *; + static constexpr bool IsPostDominator = IsPostDom; + + DominatorTreeBase() {} DominatorTreeBase(DominatorTreeBase &&Arg) : Roots(std::move(Arg.Roots)), - IsPostDominators(Arg.IsPostDominators), DomTreeNodes(std::move(Arg.DomTreeNodes)), - RootNode(std::move(Arg.RootNode)), - DFSInfoValid(std::move(Arg.DFSInfoValid)), - SlowQueries(std::move(Arg.SlowQueries)) { + RootNode(Arg.RootNode), + Parent(Arg.Parent), + DFSInfoValid(Arg.DFSInfoValid), + SlowQueries(Arg.SlowQueries) { Arg.wipe(); } DominatorTreeBase &operator=(DominatorTreeBase &&RHS) { Roots = std::move(RHS.Roots); - IsPostDominators = RHS.IsPostDominators; DomTreeNodes = std::move(RHS.DomTreeNodes); - RootNode = std::move(RHS.RootNode); - DFSInfoValid = std::move(RHS.DFSInfoValid); - SlowQueries = std::move(RHS.SlowQueries); + RootNode = RHS.RootNode; + Parent = RHS.Parent; + DFSInfoValid = RHS.DFSInfoValid; + SlowQueries = RHS.SlowQueries; RHS.wipe(); return *this; } @@ -259,11 +264,12 @@ template <class NodeT> class DominatorTreeBase { /// isPostDominator - Returns true if analysis based of postdoms /// - bool isPostDominator() const { return IsPostDominators; } + bool isPostDominator() const { return IsPostDominator; } /// compare - Return false if the other dominator tree base matches this /// dominator tree base. Otherwise return true. bool compare(const DominatorTreeBase &Other) const { + if (Parent != Other.Parent) return true; const DomTreeNodeMapType &OtherDomTreeNodes = Other.DomTreeNodes; if (DomTreeNodes.size() != OtherDomTreeNodes.size()) @@ -443,10 +449,50 @@ template <class NodeT> class DominatorTreeBase { const_cast<NodeT *>(B)); } + bool isVirtualRoot(const DomTreeNodeBase<NodeT> *A) const { + return isPostDominator() && !A->getBlock(); + } + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... + /// Inform the dominator tree about a CFG edge insertion and update the tree. + /// + /// This function has to be called just before or just after making the update + /// on the actual CFG. There cannot be any other updates that the dominator + /// tree doesn't know about. + /// + /// Note that for postdominators it automatically takes care of inserting + /// a reverse edge internally (so there's no need to swap the parameters). + /// + void insertEdge(NodeT *From, NodeT *To) { + assert(From); + assert(To); + assert(From->getParent() == Parent); + assert(To->getParent() == Parent); + DomTreeBuilder::InsertEdge(*this, From, To); + } + + /// Inform the dominator tree about a CFG edge deletion and update the tree. + /// + /// This function has to be called just after making the update + /// on the actual CFG. There cannot be any other updates that the dominator + /// tree doesn't know about. The only exception is when the deletion that the + /// tree is informed about makes some (domominator) subtree unreachable -- in + /// this case, it is fine to perform deletions within this subtree. + /// + /// Note that for postdominators it automatically takes care of deleting + /// a reverse edge internally (so there's no need to swap the parameters). + /// + void deleteEdge(NodeT *From, NodeT *To) { + assert(From); + assert(To); + assert(From->getParent() == Parent); + assert(To->getParent() == Parent); + DomTreeBuilder::DeleteEdge(*this, From, To); + } + /// Add a new node to the dominator tree information. /// /// This creates a new node as a child of DomBB dominator node, linking it @@ -530,7 +576,7 @@ template <class NodeT> class DominatorTreeBase { /// splitBlock - BB is split and now it has one successor. Update dominator /// tree to reflect this change. void splitBlock(NodeT *NewBB) { - if (this->IsPostDominators) + if (IsPostDominator) Split<Inverse<NodeT *>>(NewBB); else Split<NodeT *>(NewBB); @@ -607,37 +653,33 @@ public: template <class FT> void recalculate(FT &F) { using TraitsTy = GraphTraits<FT *>; reset(); + Parent = &F; - if (!this->IsPostDominators) { + if (!IsPostDominator) { // Initialize root NodeT *entry = TraitsTy::getEntryNode(&F); addRoot(entry); - - DomTreeBuilder::Calculate<FT, NodeT *>(*this, F); } else { // Initialize the roots list for (auto *Node : nodes(&F)) if (TraitsTy::child_begin(Node) == TraitsTy::child_end(Node)) addRoot(Node); - - DomTreeBuilder::Calculate<FT, Inverse<NodeT *>>(*this, F); } + + DomTreeBuilder::Calculate(*this, F); } /// verify - check parent and sibling property - bool verify() const { - return this->isPostDominator() - ? DomTreeBuilder::Verify<Inverse<NodeT *>>(*this) - : DomTreeBuilder::Verify<NodeT *>(*this); - } + bool verify() const { return DomTreeBuilder::Verify(*this); } protected: void addRoot(NodeT *BB) { this->Roots.push_back(BB); } void reset() { DomTreeNodes.clear(); - this->Roots.clear(); + Roots.clear(); RootNode = nullptr; + Parent = nullptr; DFSInfoValid = false; SlowQueries = 0; } @@ -719,13 +761,21 @@ public: void wipe() { DomTreeNodes.clear(); RootNode = nullptr; + Parent = nullptr; } }; +template <typename T> +using DomTreeBase = DominatorTreeBase<T, false>; + +template <typename T> +using PostDomTreeBase = DominatorTreeBase<T, true>; + // These two functions are declared out of line as a workaround for building // with old (< r147295) versions of clang because of pr11642. -template <class NodeT> -bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { +template <typename NodeT, bool IsPostDom> +bool DominatorTreeBase<NodeT, IsPostDom>::dominates(const NodeT *A, + const NodeT *B) const { if (A == B) return true; @@ -735,9 +785,9 @@ bool DominatorTreeBase<NodeT>::dominates(const NodeT *A, const NodeT *B) const { return dominates(getNode(const_cast<NodeT *>(A)), getNode(const_cast<NodeT *>(B))); } -template <class NodeT> -bool DominatorTreeBase<NodeT>::properlyDominates(const NodeT *A, - const NodeT *B) const { +template <typename NodeT, bool IsPostDom> +bool DominatorTreeBase<NodeT, IsPostDom>::properlyDominates( + const NodeT *A, const NodeT *B) const { if (A == B) return false; diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index a0fec668e05c..be90afa4c3c8 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -20,15 +20,28 @@ /// out that the theoretically slower O(n*log(n)) implementation is actually /// faster than the almost-linear O(n*alpha(n)) version, even for large CFGs. /// +/// The file uses the Depth Based Search algorithm to perform incremental +/// upates (insertion and deletions). The implemented algorithm is based on this +/// publication: +/// +/// An Experimental Study of Dynamic Dominators +/// Loukas Georgiadis, et al., April 12 2016, pp. 5-7, 9-10: +/// https://arxiv.org/pdf/1604.02711.pdf +/// //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H #define LLVM_SUPPORT_GENERICDOMTREECONSTRUCTION_H +#include <queue> +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/GenericDomTree.h" +#define DEBUG_TYPE "dom-tree-builder" + namespace llvm { namespace DomTreeBuilder { @@ -46,13 +59,14 @@ struct ChildrenGetter<NodePtr, true> { } }; -// Information record used by Semi-NCA during tree construction. -template <typename NodeT> +template <typename DomTreeT> struct SemiNCAInfo { - using NodePtr = NodeT *; - using DomTreeT = DominatorTreeBase<NodeT>; + using NodePtr = typename DomTreeT::NodePtr; + using NodeT = typename DomTreeT::NodeType; using TreeNodePtr = DomTreeNodeBase<NodeT> *; + static constexpr bool IsPostDom = DomTreeT::IsPostDominator; + // Information record used by Semi-NCA during tree construction. struct InfoRec { unsigned DFSNum = 0; unsigned Parent = 0; @@ -62,11 +76,13 @@ struct SemiNCAInfo { SmallVector<NodePtr, 2> ReverseChildren; }; - std::vector<NodePtr> NumToNode; + // Number to node mapping is 1-based. Initialize the mapping to start with + // a dummy element. + std::vector<NodePtr> NumToNode = {nullptr}; DenseMap<NodePtr, InfoRec> NodeToInfo; void clear() { - NumToNode.clear(); + NumToNode = {nullptr}; // Restore to initial state with a dummy start node. NodeToInfo.clear(); } @@ -90,12 +106,28 @@ struct SemiNCAInfo { // Add a new tree node for this NodeT, and link it as a child of // IDomNode return (DT.DomTreeNodes[BB] = IDomNode->addChild( - llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))) .get(); } static bool AlwaysDescend(NodePtr, NodePtr) { return true; } + struct BlockNamePrinter { + NodePtr N; + + BlockNamePrinter(NodePtr Block) : N(Block) {} + BlockNamePrinter(TreeNodePtr TN) : N(TN ? TN->getBlock() : nullptr) {} + + friend raw_ostream &operator<<(raw_ostream &O, const BlockNamePrinter &BP) { + if (!BP.N) + O << "nullptr"; + else + BP.N->printAsOperand(O, false); + + return O; + } + }; + // Custom DFS implementation which can skip nodes based on a provided // predicate. It also collects ReverseChildren so that we don't have to spend // time getting predecessors in SemiNCA. @@ -177,44 +209,42 @@ struct SemiNCAInfo { return VInInfo.Label; } - template <typename NodeType> - void runSemiNCA(DomTreeT &DT, unsigned NumBlocks) { - // Step #1: Number blocks in depth-first order and initialize variables used - // in later stages of the algorithm. - const unsigned N = doFullDFSWalk(DT, AlwaysDescend); - - // It might be that some blocks did not get a DFS number (e.g., blocks of - // infinite loops). In these cases an artificial exit node is required. - const bool MultipleRoots = - DT.Roots.size() > 1 || (DT.isPostDominator() && N != NumBlocks); - + // This function requires DFS to be run before calling it. + void runSemiNCA(DomTreeT &DT, const unsigned MinLevel = 0) { + const unsigned NextDFSNum(NumToNode.size()); // Initialize IDoms to spanning tree parents. - for (unsigned i = 1; i <= N; ++i) { + for (unsigned i = 1; i < NextDFSNum; ++i) { const NodePtr V = NumToNode[i]; auto &VInfo = NodeToInfo[V]; VInfo.IDom = NumToNode[VInfo.Parent]; } - // Step #2: Calculate the semidominators of all vertices. - for (unsigned i = N; i >= 2; --i) { + // Step #1: Calculate the semidominators of all vertices. + for (unsigned i = NextDFSNum - 1; i >= 2; --i) { NodePtr W = NumToNode[i]; auto &WInfo = NodeToInfo[W]; // Initialize the semi dominator to point to the parent node. WInfo.Semi = WInfo.Parent; - for (const auto &N : WInfo.ReverseChildren) - if (NodeToInfo.count(N)) { // Only if this predecessor is reachable! - unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi; - if (SemiU < WInfo.Semi) - WInfo.Semi = SemiU; - } + for (const auto &N : WInfo.ReverseChildren) { + if (NodeToInfo.count(N) == 0) // Skip unreachable predecessors. + continue; + + const TreeNodePtr TN = DT.getNode(N); + // Skip predecessors whose level is above the subtree we are processing. + if (TN && TN->getLevel() < MinLevel) + continue; + + unsigned SemiU = NodeToInfo[eval(N, i + 1)].Semi; + if (SemiU < WInfo.Semi) WInfo.Semi = SemiU; + } } - // Step #3: Explicitly define the immediate dominator of each vertex. + // Step #2: Explicitly define the immediate dominator of each vertex. // IDom[i] = NCA(SDom[i], SpanningTreeParent(i)). // Note that the parents were stored in IDoms and later got invalidated // during path compression in Eval. - for (unsigned i = 2; i <= N; ++i) { + for (unsigned i = 2; i < NextDFSNum; ++i) { const NodePtr W = NumToNode[i]; auto &WInfo = NodeToInfo[W]; const unsigned SDomNum = NodeToInfo[NumToNode[WInfo.Semi]].DFSNum; @@ -224,6 +254,36 @@ struct SemiNCAInfo { WInfo.IDom = WIDomCandidate; } + } + + template <typename DescendCondition> + unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { + unsigned Num = 0; + + if (DT.Roots.size() > 1) { + auto &BBInfo = NodeToInfo[nullptr]; + BBInfo.DFSNum = BBInfo.Semi = ++Num; + BBInfo.Label = nullptr; + + NumToNode.push_back(nullptr); // NumToNode[n] = V; + } + + if (DT.isPostDominator()) { + for (auto *Root : DT.Roots) Num = runDFS<true>(Root, Num, DC, 1); + } else { + assert(DT.Roots.size() == 1); + Num = runDFS<false>(DT.Roots[0], Num, DC, Num); + } + + return Num; + } + + void calculateFromScratch(DomTreeT &DT, const unsigned NumBlocks) { + // Step #0: Number blocks in depth-first order and initialize variables used + // in later stages of the algorithm. + const unsigned LastDFSNum = doFullDFSWalk(DT, AlwaysDescend); + + runSemiNCA(DT); if (DT.Roots.empty()) return; @@ -231,25 +291,32 @@ struct SemiNCAInfo { // one exit block, or it may be the virtual exit (denoted by // (BasicBlock *)0) which postdominates all real exits if there are multiple // exit blocks, or an infinite loop. + // It might be that some blocks did not get a DFS number (e.g., blocks of + // infinite loops). In these cases an artificial exit node is required. + const bool MultipleRoots = DT.Roots.size() > 1 || (DT.isPostDominator() && + LastDFSNum != NumBlocks); NodePtr Root = !MultipleRoots ? DT.Roots[0] : nullptr; - DT.RootNode = - (DT.DomTreeNodes[Root] = - llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) - .get(); + DT.RootNode = (DT.DomTreeNodes[Root] = + llvm::make_unique<DomTreeNodeBase<NodeT>>(Root, nullptr)) + .get(); + attachNewSubtree(DT, DT.RootNode); + } - // Loop over all of the reachable blocks in the function... - for (unsigned i = 2; i <= N; ++i) { + void attachNewSubtree(DomTreeT& DT, const TreeNodePtr AttachTo) { + // Attach the first unreachable block to AttachTo. + NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); + // Loop over all of the discovered blocks in the function... + for (size_t i = 1, e = NumToNode.size(); i != e; ++i) { NodePtr W = NumToNode[i]; + DEBUG(dbgs() << "\tdiscovered a new reachable node " + << BlockNamePrinter(W) << "\n"); // Don't replace this with 'count', the insertion side effect is important - if (DT.DomTreeNodes[W]) - continue; // Haven't calculated this node yet? + if (DT.DomTreeNodes[W]) continue; // Haven't calculated this node yet? NodePtr ImmDom = getIDom(W); - assert(ImmDom || DT.DomTreeNodes[nullptr]); - // Get or calculate the node for the immediate dominator TreeNodePtr IDomNode = getNodeForBlock(ImmDom, DT); @@ -260,34 +327,208 @@ struct SemiNCAInfo { } } - template <typename DescendCondition> - unsigned doFullDFSWalk(const DomTreeT &DT, DescendCondition DC) { - unsigned Num = 0; - NumToNode.push_back(nullptr); + void reattachExistingSubtree(DomTreeT &DT, const TreeNodePtr AttachTo) { + NodeToInfo[NumToNode[1]].IDom = AttachTo->getBlock(); + for (size_t i = 1, e = NumToNode.size(); i != e; ++i) { + const NodePtr N = NumToNode[i]; + const TreeNodePtr TN = DT.getNode(N); + assert(TN); + const TreeNodePtr NewIDom = DT.getNode(NodeToInfo[N].IDom); + TN->setIDom(NewIDom); + } + } - if (DT.Roots.size() > 1) { - auto &BBInfo = NodeToInfo[nullptr]; - BBInfo.DFSNum = BBInfo.Semi = ++Num; - BBInfo.Label = nullptr; + // Helper struct used during edge insertions. + struct InsertionInfo { + using BucketElementTy = std::pair<unsigned, TreeNodePtr>; + struct DecreasingLevel { + bool operator()(const BucketElementTy &First, + const BucketElementTy &Second) const { + return First.first > Second.first; + } + }; + + std::priority_queue<BucketElementTy, SmallVector<BucketElementTy, 8>, + DecreasingLevel> + Bucket; // Queue of tree nodes sorted by level in descending order. + SmallDenseSet<TreeNodePtr, 8> Affected; + SmallDenseSet<TreeNodePtr, 8> Visited; + SmallVector<TreeNodePtr, 8> AffectedQueue; + SmallVector<TreeNodePtr, 8> VisitedNotAffectedQueue; + }; - NumToNode.push_back(nullptr); // NumToNode[n] = V; + static void InsertEdge(DomTreeT &DT, const NodePtr From, const NodePtr To) { + assert(From && To && "Cannot connect nullptrs"); + DEBUG(dbgs() << "Inserting edge " << BlockNamePrinter(From) << " -> " + << BlockNamePrinter(To) << "\n"); + const TreeNodePtr FromTN = DT.getNode(From); + + // Ignore edges from unreachable nodes. + if (!FromTN) return; + + DT.DFSInfoValid = false; + + const TreeNodePtr ToTN = DT.getNode(To); + if (!ToTN) + InsertUnreachable(DT, FromTN, To); + else + InsertReachable(DT, FromTN, ToTN); + } + + // Handles insertion to a node already in the dominator tree. + static void InsertReachable(DomTreeT &DT, const TreeNodePtr From, + const TreeNodePtr To) { + DEBUG(dbgs() << "\tReachable " << BlockNamePrinter(From->getBlock()) + << " -> " << BlockNamePrinter(To->getBlock()) << "\n"); + const NodePtr NCDBlock = + DT.findNearestCommonDominator(From->getBlock(), To->getBlock()); + assert(NCDBlock || DT.isPostDominator()); + const TreeNodePtr NCD = DT.getNode(NCDBlock); + assert(NCD); + + DEBUG(dbgs() << "\t\tNCA == " << BlockNamePrinter(NCD) << "\n"); + const TreeNodePtr ToIDom = To->getIDom(); + + // Nothing affected -- NCA property holds. + // (Based on the lemma 2.5 from the second paper.) + if (NCD == To || NCD == ToIDom) return; + + // Identify and collect affected nodes. + InsertionInfo II; + DEBUG(dbgs() << "Marking " << BlockNamePrinter(To) << " as affected\n"); + II.Affected.insert(To); + const unsigned ToLevel = To->getLevel(); + DEBUG(dbgs() << "Putting " << BlockNamePrinter(To) << " into a Bucket\n"); + II.Bucket.push({ToLevel, To}); + + while (!II.Bucket.empty()) { + const TreeNodePtr CurrentNode = II.Bucket.top().second; + II.Bucket.pop(); + DEBUG(dbgs() << "\tAdding to Visited and AffectedQueue: " + << BlockNamePrinter(CurrentNode) << "\n"); + II.Visited.insert(CurrentNode); + II.AffectedQueue.push_back(CurrentNode); + + // Discover and collect affected successors of the current node. + VisitInsertion(DT, CurrentNode, CurrentNode->getLevel(), NCD, II); } - if (DT.isPostDominator()) { - for (auto *Root : DT.Roots) Num = runDFS<true>(Root, Num, DC, 1); - } else { - assert(DT.Roots.size() == 1); - Num = runDFS<false>(DT.Roots[0], Num, DC, Num); + // Finish by updating immediate dominators and levels. + UpdateInsertion(DT, NCD, II); + } + + // Visits an affected node and collect its affected successors. + static void VisitInsertion(DomTreeT &DT, const TreeNodePtr TN, + const unsigned RootLevel, const TreeNodePtr NCD, + InsertionInfo &II) { + const unsigned NCDLevel = NCD->getLevel(); + DEBUG(dbgs() << "Visiting " << BlockNamePrinter(TN) << "\n"); + + assert(TN->getBlock()); + for (const NodePtr Succ : + ChildrenGetter<NodePtr, IsPostDom>::Get(TN->getBlock())) { + const TreeNodePtr SuccTN = DT.getNode(Succ); + assert(SuccTN && "Unreachable successor found at reachable insertion"); + const unsigned SuccLevel = SuccTN->getLevel(); + + DEBUG(dbgs() << "\tSuccessor " << BlockNamePrinter(Succ) + << ", level = " << SuccLevel << "\n"); + + // Succ dominated by subtree From -- not affected. + // (Based on the lemma 2.5 from the second paper.) + if (SuccLevel > RootLevel) { + DEBUG(dbgs() << "\t\tDominated by subtree From\n"); + if (II.Visited.count(SuccTN) != 0) continue; + + DEBUG(dbgs() << "\t\tMarking visited not affected " + << BlockNamePrinter(Succ) << "\n"); + II.Visited.insert(SuccTN); + II.VisitedNotAffectedQueue.push_back(SuccTN); + VisitInsertion(DT, SuccTN, RootLevel, NCD, II); + } else if ((SuccLevel > NCDLevel + 1) && II.Affected.count(SuccTN) == 0) { + DEBUG(dbgs() << "\t\tMarking affected and adding " + << BlockNamePrinter(Succ) << " to a Bucket\n"); + II.Affected.insert(SuccTN); + II.Bucket.push({SuccLevel, SuccTN}); + } } + } - return Num; + // Updates immediate dominators and levels after insertion. + static void UpdateInsertion(DomTreeT &DT, const TreeNodePtr NCD, + InsertionInfo &II) { + DEBUG(dbgs() << "Updating NCD = " << BlockNamePrinter(NCD) << "\n"); + + for (const TreeNodePtr TN : II.AffectedQueue) { + DEBUG(dbgs() << "\tIDom(" << BlockNamePrinter(TN) + << ") = " << BlockNamePrinter(NCD) << "\n"); + TN->setIDom(NCD); + } + + UpdateLevelsAfterInsertion(II); } - static void PrintBlockOrNullptr(raw_ostream &O, NodePtr Obj) { - if (!Obj) - O << "nullptr"; - else - Obj->printAsOperand(O, false); + static void UpdateLevelsAfterInsertion(InsertionInfo &II) { + DEBUG(dbgs() << "Updating levels for visited but not affected nodes\n"); + + for (const TreeNodePtr TN : II.VisitedNotAffectedQueue) { + DEBUG(dbgs() << "\tlevel(" << BlockNamePrinter(TN) << ") = (" + << BlockNamePrinter(TN->getIDom()) << ") " + << TN->getIDom()->getLevel() << " + 1\n"); + TN->UpdateLevel(); + } + } + + // Handles insertion to previously unreachable nodes. + static void InsertUnreachable(DomTreeT &DT, const TreeNodePtr From, + const NodePtr To) { + DEBUG(dbgs() << "Inserting " << BlockNamePrinter(From) + << " -> (unreachable) " << BlockNamePrinter(To) << "\n"); + + // Collect discovered edges to already reachable nodes. + SmallVector<std::pair<NodePtr, TreeNodePtr>, 8> DiscoveredEdgesToReachable; + // Discover and connect nodes that became reachable with the insertion. + ComputeUnreachableDominators(DT, To, From, DiscoveredEdgesToReachable); + + DEBUG(dbgs() << "Inserted " << BlockNamePrinter(From) + << " -> (prev unreachable) " << BlockNamePrinter(To) << "\n"); + + DEBUG(DT.print(dbgs())); + + // Used the discovered edges and inset discovered connecting (incoming) + // edges. + for (const auto &Edge : DiscoveredEdgesToReachable) { + DEBUG(dbgs() << "\tInserting discovered connecting edge " + << BlockNamePrinter(Edge.first) << " -> " + << BlockNamePrinter(Edge.second) << "\n"); + InsertReachable(DT, DT.getNode(Edge.first), Edge.second); + } + } + + // Connects nodes that become reachable with an insertion. + static void ComputeUnreachableDominators( + DomTreeT &DT, const NodePtr Root, const TreeNodePtr Incoming, + SmallVectorImpl<std::pair<NodePtr, TreeNodePtr>> + &DiscoveredConnectingEdges) { + assert(!DT.getNode(Root) && "Root must not be reachable"); + + // Visit only previously unreachable nodes. + auto UnreachableDescender = [&DT, &DiscoveredConnectingEdges](NodePtr From, + NodePtr To) { + const TreeNodePtr ToTN = DT.getNode(To); + if (!ToTN) return true; + + DiscoveredConnectingEdges.push_back({From, ToTN}); + return false; + }; + + SemiNCAInfo SNCA; + SNCA.runDFS<IsPostDom>(Root, 0, UnreachableDescender, 0); + SNCA.runSemiNCA(DT); + SNCA.attachNewSubtree(DT, Incoming); + + DEBUG(dbgs() << "After adding unreachable nodes\n"); + DEBUG(DT.print(dbgs())); } // Checks if the tree contains all reachable nodes in the input graph. @@ -298,12 +539,23 @@ struct SemiNCAInfo { for (auto &NodeToTN : DT.DomTreeNodes) { const TreeNodePtr TN = NodeToTN.second.get(); const NodePtr BB = TN->getBlock(); - if (!BB) continue; + + // Virtual root has a corresponding virtual CFG node. + if (DT.isVirtualRoot(TN)) continue; if (NodeToInfo.count(BB) == 0) { - errs() << "DomTree node "; - PrintBlockOrNullptr(errs(), BB); - errs() << " not found by DFS walk!\n"; + errs() << "DomTree node " << BlockNamePrinter(BB) + << " not found by DFS walk!\n"; + errs().flush(); + + return false; + } + } + + for (const NodePtr N : NumToNode) { + if (N && !DT.getNode(N)) { + errs() << "CFG node " << BlockNamePrinter(N) + << " not found in the DomTree!\n"; errs().flush(); return false; @@ -313,6 +565,215 @@ struct SemiNCAInfo { return true; } + static void DeleteEdge(DomTreeT &DT, const NodePtr From, const NodePtr To) { + assert(From && To && "Cannot disconnect nullptrs"); + DEBUG(dbgs() << "Deleting edge " << BlockNamePrinter(From) << " -> " + << BlockNamePrinter(To) << "\n"); + +#ifndef NDEBUG + // Ensure that the edge was in fact deleted from the CFG before informing + // the DomTree about it. + // The check is O(N), so run it only in debug configuration. + auto IsSuccessor = [](const NodePtr SuccCandidate, const NodePtr Of) { + auto Successors = ChildrenGetter<NodePtr, IsPostDom>::Get(Of); + return llvm::find(Successors, SuccCandidate) != Successors.end(); + }; + (void)IsSuccessor; + assert(!IsSuccessor(To, From) && "Deleted edge still exists in the CFG!"); +#endif + + const TreeNodePtr FromTN = DT.getNode(From); + // Deletion in an unreachable subtree -- nothing to do. + if (!FromTN) return; + + const TreeNodePtr ToTN = DT.getNode(To); + assert(ToTN && "To already unreachable -- there is no edge to delete"); + const NodePtr NCDBlock = DT.findNearestCommonDominator(From, To); + const TreeNodePtr NCD = DT.getNode(NCDBlock); + + // To dominates From -- nothing to do. + if (ToTN == NCD) return; + + const TreeNodePtr ToIDom = ToTN->getIDom(); + DEBUG(dbgs() << "\tNCD " << BlockNamePrinter(NCD) << ", ToIDom " + << BlockNamePrinter(ToIDom) << "\n"); + + // To remains reachable after deletion. + // (Based on the caption under Figure 4. from the second paper.) + if (FromTN != ToIDom || HasProperSupport(DT, ToTN)) + DeleteReachable(DT, FromTN, ToTN); + else + DeleteUnreachable(DT, ToTN); + } + + // Handles deletions that leave destination nodes reachable. + static void DeleteReachable(DomTreeT &DT, const TreeNodePtr FromTN, + const TreeNodePtr ToTN) { + DEBUG(dbgs() << "Deleting reachable " << BlockNamePrinter(FromTN) << " -> " + << BlockNamePrinter(ToTN) << "\n"); + DEBUG(dbgs() << "\tRebuilding subtree\n"); + + // Find the top of the subtree that needs to be rebuilt. + // (Based on the lemma 2.6 from the second paper.) + const NodePtr ToIDom = + DT.findNearestCommonDominator(FromTN->getBlock(), ToTN->getBlock()); + assert(ToIDom || DT.isPostDominator()); + const TreeNodePtr ToIDomTN = DT.getNode(ToIDom); + assert(ToIDomTN); + const TreeNodePtr PrevIDomSubTree = ToIDomTN->getIDom(); + // Top of the subtree to rebuild is the root node. Rebuild the tree from + // scratch. + if (!PrevIDomSubTree) { + DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); + DT.recalculate(*DT.Parent); + return; + } + + // Only visit nodes in the subtree starting at To. + const unsigned Level = ToIDomTN->getLevel(); + auto DescendBelow = [Level, &DT](NodePtr, NodePtr To) { + return DT.getNode(To)->getLevel() > Level; + }; + + DEBUG(dbgs() << "\tTop of subtree: " << BlockNamePrinter(ToIDomTN) << "\n"); + + SemiNCAInfo SNCA; + SNCA.runDFS<IsPostDom>(ToIDom, 0, DescendBelow, 0); + DEBUG(dbgs() << "\tRunning Semi-NCA\n"); + SNCA.runSemiNCA(DT, Level); + SNCA.reattachExistingSubtree(DT, PrevIDomSubTree); + } + + // Checks if a node has proper support, as defined on the page 3 and later + // explained on the page 7 of the second paper. + static bool HasProperSupport(DomTreeT &DT, const TreeNodePtr TN) { + DEBUG(dbgs() << "IsReachableFromIDom " << BlockNamePrinter(TN) << "\n"); + for (const NodePtr Pred : + ChildrenGetter<NodePtr, !IsPostDom>::Get(TN->getBlock())) { + DEBUG(dbgs() << "\tPred " << BlockNamePrinter(Pred) << "\n"); + if (!DT.getNode(Pred)) continue; + + const NodePtr Support = + DT.findNearestCommonDominator(TN->getBlock(), Pred); + DEBUG(dbgs() << "\tSupport " << BlockNamePrinter(Support) << "\n"); + if (Support != TN->getBlock()) { + DEBUG(dbgs() << "\t" << BlockNamePrinter(TN) + << " is reachable from support " + << BlockNamePrinter(Support) << "\n"); + return true; + } + } + + return false; + } + + // Handle deletions that make destination node unreachable. + // (Based on the lemma 2.7 from the second paper.) + static void DeleteUnreachable(DomTreeT &DT, const TreeNodePtr ToTN) { + DEBUG(dbgs() << "Deleting unreachable subtree " << BlockNamePrinter(ToTN) + << "\n"); + assert(ToTN); + assert(ToTN->getBlock()); + + SmallVector<NodePtr, 16> AffectedQueue; + const unsigned Level = ToTN->getLevel(); + + // Traverse destination node's descendants with greater level in the tree + // and collect visited nodes. + auto DescendAndCollect = [Level, &AffectedQueue, &DT](NodePtr, NodePtr To) { + const TreeNodePtr TN = DT.getNode(To); + assert(TN); + if (TN->getLevel() > Level) return true; + if (llvm::find(AffectedQueue, To) == AffectedQueue.end()) + AffectedQueue.push_back(To); + + return false; + }; + + SemiNCAInfo SNCA; + unsigned LastDFSNum = + SNCA.runDFS<IsPostDom>(ToTN->getBlock(), 0, DescendAndCollect, 0); + + TreeNodePtr MinNode = ToTN; + + // Identify the top of the subtree to rebuilt by finding the NCD of all + // the affected nodes. + for (const NodePtr N : AffectedQueue) { + const TreeNodePtr TN = DT.getNode(N); + const NodePtr NCDBlock = + DT.findNearestCommonDominator(TN->getBlock(), ToTN->getBlock()); + assert(NCDBlock || DT.isPostDominator()); + const TreeNodePtr NCD = DT.getNode(NCDBlock); + assert(NCD); + + DEBUG(dbgs() << "Processing affected node " << BlockNamePrinter(TN) + << " with NCD = " << BlockNamePrinter(NCD) + << ", MinNode =" << BlockNamePrinter(MinNode) << "\n"); + if (NCD != TN && NCD->getLevel() < MinNode->getLevel()) MinNode = NCD; + } + + // Root reached, rebuild the whole tree from scratch. + if (!MinNode->getIDom()) { + DEBUG(dbgs() << "The entire tree needs to be rebuilt\n"); + DT.recalculate(*DT.Parent); + return; + } + + // Erase the unreachable subtree in reverse preorder to process all children + // before deleting their parent. + for (unsigned i = LastDFSNum; i > 0; --i) { + const NodePtr N = SNCA.NumToNode[i]; + const TreeNodePtr TN = DT.getNode(N); + DEBUG(dbgs() << "Erasing node " << BlockNamePrinter(TN) << "\n"); + + EraseNode(DT, TN); + } + + // The affected subtree start at the To node -- there's no extra work to do. + if (MinNode == ToTN) return; + + DEBUG(dbgs() << "DeleteUnreachable: running DFS with MinNode = " + << BlockNamePrinter(MinNode) << "\n"); + const unsigned MinLevel = MinNode->getLevel(); + const TreeNodePtr PrevIDom = MinNode->getIDom(); + assert(PrevIDom); + SNCA.clear(); + + // Identify nodes that remain in the affected subtree. + auto DescendBelow = [MinLevel, &DT](NodePtr, NodePtr To) { + const TreeNodePtr ToTN = DT.getNode(To); + return ToTN && ToTN->getLevel() > MinLevel; + }; + SNCA.runDFS<IsPostDom>(MinNode->getBlock(), 0, DescendBelow, 0); + + DEBUG(dbgs() << "Previous IDom(MinNode) = " << BlockNamePrinter(PrevIDom) + << "\nRunning Semi-NCA\n"); + + // Rebuild the remaining part of affected subtree. + SNCA.runSemiNCA(DT, MinLevel); + SNCA.reattachExistingSubtree(DT, PrevIDom); + } + + // Removes leaf tree nodes from the dominator tree. + static void EraseNode(DomTreeT &DT, const TreeNodePtr TN) { + assert(TN); + assert(TN->getNumChildren() == 0 && "Not a tree leaf"); + + const TreeNodePtr IDom = TN->getIDom(); + assert(IDom); + + auto ChIt = llvm::find(IDom->Children, TN); + assert(ChIt != IDom->Children.end()); + std::swap(*ChIt, IDom->Children.back()); + IDom->Children.pop_back(); + + DT.DomTreeNodes.erase(TN->getBlock()); + } + + //~~ + //===--------------- DomTree correctness verification ---------------------=== + //~~ + // Check if for every parent with a level L in the tree all of its children // have level L + 1. static bool VerifyLevels(const DomTreeT &DT) { @@ -323,20 +784,18 @@ struct SemiNCAInfo { const TreeNodePtr IDom = TN->getIDom(); if (!IDom && TN->getLevel() != 0) { - errs() << "Node without an IDom "; - PrintBlockOrNullptr(errs(), BB); - errs() << " has a nonzero level " << TN->getLevel() << "!\n"; + errs() << "Node without an IDom " << BlockNamePrinter(BB) + << " has a nonzero level " << TN->getLevel() << "!\n"; errs().flush(); return false; } if (IDom && TN->getLevel() != IDom->getLevel() + 1) { - errs() << "Node "; - PrintBlockOrNullptr(errs(), BB); - errs() << " has level " << TN->getLevel() << " while it's IDom "; - PrintBlockOrNullptr(errs(), IDom->getBlock()); - errs() << " has level " << IDom->getLevel() << "!\n"; + errs() << "Node " << BlockNamePrinter(BB) << " has level " + << TN->getLevel() << " while its IDom " + << BlockNamePrinter(IDom->getBlock()) << " has level " + << IDom->getLevel() << "!\n"; errs().flush(); return false; @@ -363,18 +822,14 @@ struct SemiNCAInfo { assert(ToTN); const NodePtr NCD = DT.findNearestCommonDominator(From, To); - const TreeNodePtr NCDTN = NCD ? DT.getNode(NCD) : nullptr; + const TreeNodePtr NCDTN = DT.getNode(NCD); const TreeNodePtr ToIDom = ToTN->getIDom(); if (NCDTN != ToTN && NCDTN != ToIDom) { - errs() << "NearestCommonDominator verification failed:\n\tNCD(From:"; - PrintBlockOrNullptr(errs(), From); - errs() << ", To:"; - PrintBlockOrNullptr(errs(), To); - errs() << ") = "; - PrintBlockOrNullptr(errs(), NCD); - errs() << ",\t (should be To or IDom[To]: "; - PrintBlockOrNullptr(errs(), ToIDom ? ToIDom->getBlock() : nullptr); - errs() << ")\n"; + errs() << "NearestCommonDominator verification failed:\n\tNCD(From:" + << BlockNamePrinter(From) << ", To:" << BlockNamePrinter(To) + << ") = " << BlockNamePrinter(NCD) + << ",\t (should be To or IDom[To]: " << BlockNamePrinter(ToIDom) + << ")\n"; errs().flush(); return false; @@ -440,11 +895,9 @@ struct SemiNCAInfo { for (TreeNodePtr Child : TN->getChildren()) if (NodeToInfo.count(Child->getBlock()) != 0) { - errs() << "Child "; - PrintBlockOrNullptr(errs(), Child->getBlock()); - errs() << " reachable after its parent "; - PrintBlockOrNullptr(errs(), BB); - errs() << " is removed!\n"; + errs() << "Child " << BlockNamePrinter(Child) + << " reachable after its parent " << BlockNamePrinter(BB) + << " is removed!\n"; errs().flush(); return false; @@ -477,11 +930,9 @@ struct SemiNCAInfo { if (S == N) continue; if (NodeToInfo.count(S->getBlock()) == 0) { - errs() << "Node "; - PrintBlockOrNullptr(errs(), S->getBlock()); - errs() << " not reachable when its sibling "; - PrintBlockOrNullptr(errs(), N->getBlock()); - errs() << " is removed!\n"; + errs() << "Node " << BlockNamePrinter(S) + << " not reachable when its sibling " << BlockNamePrinter(N) + << " is removed!\n"; errs().flush(); return false; @@ -494,23 +945,30 @@ struct SemiNCAInfo { } }; -template <class FuncT, class NodeT> -void Calculate(DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT, - FuncT &F) { - using NodePtr = typename GraphTraits<NodeT>::NodeRef; - static_assert(std::is_pointer<NodePtr>::value, - "NodePtr should be a pointer type"); - SemiNCAInfo<typename std::remove_pointer<NodePtr>::type> SNCA; - SNCA.template runSemiNCA<NodeT>(DT, GraphTraits<FuncT *>::size(&F)); + +template <class DomTreeT, class FuncT> +void Calculate(DomTreeT &DT, FuncT &F) { + SemiNCAInfo<DomTreeT> SNCA; + SNCA.calculateFromScratch(DT, GraphTraits<FuncT *>::size(&F)); } -template <class NodeT> -bool Verify(const DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT) { - using NodePtr = typename GraphTraits<NodeT>::NodeRef; - static_assert(std::is_pointer<NodePtr>::value, - "NodePtr should be a pointer type"); - SemiNCAInfo<typename std::remove_pointer<NodePtr>::type> SNCA; +template <class DomTreeT> +void InsertEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, + typename DomTreeT::NodePtr To) { + if (DT.isPostDominator()) std::swap(From, To); + SemiNCAInfo<DomTreeT>::InsertEdge(DT, From, To); +} + +template <class DomTreeT> +void DeleteEdge(DomTreeT &DT, typename DomTreeT::NodePtr From, + typename DomTreeT::NodePtr To) { + if (DT.isPostDominator()) std::swap(From, To); + SemiNCAInfo<DomTreeT>::DeleteEdge(DT, From, To); +} +template <class DomTreeT> +bool Verify(const DomTreeT &DT) { + SemiNCAInfo<DomTreeT> SNCA; return SNCA.verifyReachability(DT) && SNCA.VerifyLevels(DT) && SNCA.verifyNCD(DT) && SNCA.verifyParentProperty(DT) && SNCA.verifySiblingProperty(DT); @@ -519,4 +977,6 @@ bool Verify(const DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT) { } // namespace DomTreeBuilder } // namespace llvm +#undef DEBUG_TYPE + #endif diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h index 72c28865ac57..e13582f6a6d3 100644 --- a/include/llvm/Support/TargetParser.h +++ b/include/llvm/Support/TargetParser.h @@ -85,6 +85,7 @@ enum ArchExtKind : unsigned { AEK_DSP = 0x400, AEK_FP16 = 0x800, AEK_RAS = 0x1000, + AEK_SVE = 0x2000, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, @@ -166,7 +167,8 @@ enum ArchExtKind : unsigned { AEK_FP16 = 0x20, AEK_PROFILE = 0x40, AEK_RAS = 0x80, - AEK_LSE = 0x100 + AEK_LSE = 0x100, + AEK_SVE = 0x200 }; StringRef getCanonicalArchName(StringRef Arch); diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 15b3b11db045..71fdf47f1979 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -1114,6 +1114,10 @@ public: void *Ctxt = nullptr, SourceMgr::DiagHandlerTy DiagHandler = nullptr, void *DiagHandlerCtxt = nullptr); + Input(MemoryBufferRef Input, + void *Ctxt = nullptr, + SourceMgr::DiagHandlerTy DiagHandler = nullptr, + void *DiagHandlerCtxt = nullptr); ~Input() override; // Check if there was an syntax or semantic error during parsing. diff --git a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index 178b08d7b8b7..50de41fd1320 100644 --- a/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -58,6 +58,7 @@ def : GINodeEquiv<G_SITOFP, sint_to_fp>; def : GINodeEquiv<G_UITOFP, uint_to_fp>; def : GINodeEquiv<G_FADD, fadd>; def : GINodeEquiv<G_FSUB, fsub>; +def : GINodeEquiv<G_FMA, fma>; def : GINodeEquiv<G_FMUL, fmul>; def : GINodeEquiv<G_FDIV, fdiv>; def : GINodeEquiv<G_FREM, frem>; diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 60a03bdc182d..23711d636c9a 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -2012,6 +2012,35 @@ public: return isExtFreeImpl(I); } + /// Return true if \p Load and \p Ext can form an ExtLoad. + /// For example, in AArch64 + /// %L = load i8, i8* %ptr + /// %E = zext i8 %L to i32 + /// can be lowered into one load instruction + /// ldrb w0, [x0] + bool isExtLoad(const LoadInst *Load, const Instruction *Ext, + const DataLayout &DL) const { + EVT VT = getValueType(DL, Ext->getType()); + EVT LoadVT = getValueType(DL, Load->getType()); + + // If the load has other users and the truncate is not free, the ext + // probably isn't free. + if (!Load->hasOneUse() && (isTypeLegal(LoadVT) || !isTypeLegal(VT)) && + !isTruncateFree(Ext->getType(), Load->getType())) + return false; + + // Check whether the target supports casts folded into loads. + unsigned LType; + if (isa<ZExtInst>(Ext)) + LType = ISD::ZEXTLOAD; + else { + assert(isa<SExtInst>(Ext) && "Unexpected ext type!"); + LType = ISD::SEXTLOAD; + } + + return isLoadExtLegal(LType, VT, LoadVT); + } + /// Return true if any actual instruction that defines a value of type FromTy /// implicitly zero-extends the value to ToTy in the result register. /// diff --git a/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h b/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h new file mode 100644 index 000000000000..964b0f7620a2 --- /dev/null +++ b/include/llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h @@ -0,0 +1,24 @@ +//===- DlltoolDriver.h - dlltool.exe-compatible driver ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines an interface to a dlltool.exe-compatible driver. +// Used by llvm-dlltool. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLDRIVERS_LLVM_DLLTOOL_DLLTOOLDRIVER_H +#define LLVM_TOOLDRIVERS_LLVM_DLLTOOL_DLLTOOLDRIVER_H + +namespace llvm { +template <typename T> class ArrayRef; + +int dlltoolDriverMain(ArrayRef<const char *> ArgsArr); +} // namespace llvm + +#endif |