//===--- PostOrderAnalysis.h - SIL POT and RPOT Analysis -------*- C++ -*--===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SILANALYSIS_POSTORDERANALYSIS_H #define SWIFT_SILANALYSIS_POSTORDERANALYSIS_H #include "swift/SILAnalysis/Analysis.h" #include "swift/Basic/Range.h" #include "swift/SIL/CFG.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILFunction.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/DenseMap.h" #include namespace swift { class SILBasicBlock; class SILFunction; /// This class is a simple wrapper around the POT iterator provided by LLVM. It /// lazily re-evaluates the post order when it is invalidated so that we do not /// reform the post order over and over again (it can be expensive). class PostOrderAnalysis : public SILAnalysis { struct FunctionPOTInfo { bool IsInvalidated; std::vector PostOrder; FunctionPOTInfo() : IsInvalidated(true), PostOrder() {} FunctionPOTInfo(const FunctionPOTInfo &) LLVM_DELETED_FUNCTION; FunctionPOTInfo &operator=(const FunctionPOTInfo &) LLVM_DELETED_FUNCTION; FunctionPOTInfo(const FunctionPOTInfo &&F) { IsInvalidated = F.IsInvalidated; PostOrder = std::move(F.PostOrder); } FunctionPOTInfo &operator=(const FunctionPOTInfo &&F) { IsInvalidated = F.IsInvalidated; PostOrder = std::move(F.PostOrder); return *this; } void recompute(SILFunction *F) { assert(IsInvalidated && "Should only call this if the POT info is " "invalidated for this function."); PostOrder.clear(); std::copy(po_begin(F), po_end(F), std::back_inserter(PostOrder)); IsInvalidated = false; } }; llvm::DenseMap FunctionToPOTMap; public: PostOrderAnalysis(SILModule *) : SILAnalysis(AnalysisKind::PostOrder) {} // This is a cache and shouldn't be copied around. PostOrderAnalysis(const PostOrderAnalysis &) = delete; PostOrderAnalysis &operator=(const PostOrderAnalysis &) = delete; using iterator = std::vector::iterator; using reverse_iterator = std::vector::reverse_iterator; Range getPostOrder(SILFunction *F) { FunctionPOTInfo &POTInfo = FunctionToPOTMap[F]; if (POTInfo.IsInvalidated) POTInfo.recompute(F); return Range(POTInfo.PostOrder.begin(), POTInfo.PostOrder.end()); } Range getReversePostOrder(SILFunction *F) { FunctionPOTInfo &POTInfo = FunctionToPOTMap[F]; if (POTInfo.IsInvalidated) POTInfo.recompute(F); return reversed(POTInfo.PostOrder); } // Return the size of the post order for \p F. unsigned size(SILFunction *F) const { auto R = const_cast(this)->getPostOrder(F); // This is cheap since we know that we are using vector iterators. return std::distance(R.begin(), R.end()); } static bool classof(const SILAnalysis *S) { return S->getKind() == AnalysisKind::PostOrder; } virtual void invalidate(InvalidationKind K) { // FIXME: Invalidating the call graph should not invalidate the domtrees // of all functions. if (K >= InvalidationKind::CFG) { FunctionToPOTMap.clear(); } } virtual void invalidate(SILFunction* F, InvalidationKind K) { if (K >= InvalidationKind::CFG) { // Invalidate just this one function. We will lazily recompute it. FunctionToPOTMap[F].IsInvalidated = true; } } }; } // end namespace swift #endif