diff options
| author | Stephen Hines <srhines@google.com> | 2019-07-02 16:25:20 -0700 |
|---|---|---|
| committer | Ali B <abittin@gmail.com> | 2019-07-05 19:33:16 +0300 |
| commit | 9afee4e65dc5f9f5eb371683729ff67b8df81d03 (patch) | |
| tree | 4cf241d6c9044f91ee8c06e6920174d06f8de0b6 /clang-r353983e/include/llvm/PassAnalysisSupport.h | |
| parent | 2f19bd722c4c825320d1511c1ed83161b7f95d51 (diff) | |
clang 9.0.5 (based on r353983e) from build 5696680.
Bug: http://b/135931688
Bug: http://b/136008926
Test: N/A
Change-Id: I922d17410047d2e2df4625615352c588ee71b203
Diffstat (limited to 'clang-r353983e/include/llvm/PassAnalysisSupport.h')
| -rw-r--r-- | clang-r353983e/include/llvm/PassAnalysisSupport.h | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/clang-r353983e/include/llvm/PassAnalysisSupport.h b/clang-r353983e/include/llvm/PassAnalysisSupport.h new file mode 100644 index 00000000..1228534d --- /dev/null +++ b/clang-r353983e/include/llvm/PassAnalysisSupport.h @@ -0,0 +1,273 @@ +//===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines stuff that is used to define and "use" Analysis Passes. +// This file is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSANALYSISSUPPORT_H +#define LLVM_PASSANALYSISSUPPORT_H + +#include "Pass.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <utility> +#include <vector> + +namespace llvm { + +class Function; +class Pass; +class PMDataManager; + +//===----------------------------------------------------------------------===// +/// Represent the analysis usage information of a pass. This tracks analyses +/// that the pass REQUIRES (must be available when the pass runs), REQUIRES +/// TRANSITIVE (must be available throughout the lifetime of the pass), and +/// analyses that the pass PRESERVES (the pass does not invalidate the results +/// of these analyses). This information is provided by a pass to the Pass +/// infrastructure through the getAnalysisUsage virtual function. +/// +class AnalysisUsage { +public: + using VectorType = SmallVectorImpl<AnalysisID>; + +private: + /// Sets of analyses required and preserved by a pass + // TODO: It's not clear that SmallVector is an appropriate data structure for + // this usecase. The sizes were picked to minimize wasted space, but are + // otherwise fairly meaningless. + SmallVector<AnalysisID, 8> Required; + SmallVector<AnalysisID, 2> RequiredTransitive; + SmallVector<AnalysisID, 2> Preserved; + SmallVector<AnalysisID, 0> Used; + bool PreservesAll = false; + +public: + AnalysisUsage() = default; + + ///@{ + /// Add the specified ID to the required set of the usage info for a pass. + AnalysisUsage &addRequiredID(const void *ID); + AnalysisUsage &addRequiredID(char &ID); + template<class PassClass> + AnalysisUsage &addRequired() { + return addRequiredID(PassClass::ID); + } + + AnalysisUsage &addRequiredTransitiveID(char &ID); + template<class PassClass> + AnalysisUsage &addRequiredTransitive() { + return addRequiredTransitiveID(PassClass::ID); + } + ///@} + + ///@{ + /// Add the specified ID to the set of analyses preserved by this pass. + AnalysisUsage &addPreservedID(const void *ID) { + Preserved.push_back(ID); + return *this; + } + AnalysisUsage &addPreservedID(char &ID) { + Preserved.push_back(&ID); + return *this; + } + /// Add the specified Pass class to the set of analyses preserved by this pass. + template<class PassClass> + AnalysisUsage &addPreserved() { + Preserved.push_back(&PassClass::ID); + return *this; + } + ///@} + + ///@{ + /// Add the specified ID to the set of analyses used by this pass if they are + /// available.. + AnalysisUsage &addUsedIfAvailableID(const void *ID) { + Used.push_back(ID); + return *this; + } + AnalysisUsage &addUsedIfAvailableID(char &ID) { + Used.push_back(&ID); + return *this; + } + /// Add the specified Pass class to the set of analyses used by this pass. + template<class PassClass> + AnalysisUsage &addUsedIfAvailable() { + Used.push_back(&PassClass::ID); + return *this; + } + ///@} + + /// Add the Pass with the specified argument string to the set of analyses + /// preserved by this pass. If no such Pass exists, do nothing. This can be + /// useful when a pass is trivially preserved, but may not be linked in. Be + /// careful about spelling! + AnalysisUsage &addPreserved(StringRef Arg); + + /// Set by analyses that do not transform their input at all + void setPreservesAll() { PreservesAll = true; } + + /// Determine whether a pass said it does not transform its input at all + bool getPreservesAll() const { return PreservesAll; } + + /// This function should be called by the pass, iff they do not: + /// + /// 1. Add or remove basic blocks from the function + /// 2. Modify terminator instructions in any way. + /// + /// This function annotates the AnalysisUsage info object to say that analyses + /// that only depend on the CFG are preserved by this pass. + void setPreservesCFG(); + + const VectorType &getRequiredSet() const { return Required; } + const VectorType &getRequiredTransitiveSet() const { + return RequiredTransitive; + } + const VectorType &getPreservedSet() const { return Preserved; } + const VectorType &getUsedSet() const { return Used; } +}; + +//===----------------------------------------------------------------------===// +/// AnalysisResolver - Simple interface used by Pass objects to pull all +/// analysis information out of pass manager that is responsible to manage +/// the pass. +/// +class AnalysisResolver { +public: + AnalysisResolver() = delete; + explicit AnalysisResolver(PMDataManager &P) : PM(P) {} + + PMDataManager &getPMDataManager() { return PM; } + + /// Find pass that is implementing PI. + Pass *findImplPass(AnalysisID PI) { + Pass *ResultPass = nullptr; + for (const auto &AnalysisImpl : AnalysisImpls) { + if (AnalysisImpl.first == PI) { + ResultPass = AnalysisImpl.second; + break; + } + } + return ResultPass; + } + + /// Find pass that is implementing PI. Initialize pass for Function F. + Pass *findImplPass(Pass *P, AnalysisID PI, Function &F); + + void addAnalysisImplsPair(AnalysisID PI, Pass *P) { + if (findImplPass(PI) == P) + return; + std::pair<AnalysisID, Pass*> pir = std::make_pair(PI,P); + AnalysisImpls.push_back(pir); + } + + /// Clear cache that is used to connect a pass to the analysis (PassInfo). + void clearAnalysisImpls() { + AnalysisImpls.clear(); + } + + /// Return analysis result or null if it doesn't exist. + Pass *getAnalysisIfAvailable(AnalysisID ID, bool Direction) const; + +private: + /// This keeps track of which passes implements the interfaces that are + /// required by the current pass (to implement getAnalysis()). + std::vector<std::pair<AnalysisID, Pass *>> AnalysisImpls; + + /// PassManager that is used to resolve analysis info + PMDataManager &PM; +}; + +/// getAnalysisIfAvailable<AnalysisType>() - Subclasses use this function to +/// get analysis information that might be around, for example to update it. +/// This is different than getAnalysis in that it can fail (if the analysis +/// results haven't been computed), so should only be used if you can handle +/// the case when the analysis is not available. This method is often used by +/// transformation APIs to update analysis results for a pass automatically as +/// the transform is performed. +template<typename AnalysisType> +AnalysisType *Pass::getAnalysisIfAvailable() const { + assert(Resolver && "Pass not resident in a PassManager object!"); + + const void *PI = &AnalysisType::ID; + + Pass *ResultPass = Resolver->getAnalysisIfAvailable(PI, true); + if (!ResultPass) return nullptr; + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return (AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +/// getAnalysis<AnalysisType>() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +template<typename AnalysisType> +AnalysisType &Pass::getAnalysis() const { + assert(Resolver && "Pass has not been inserted into a PassManager object!"); + return getAnalysisID<AnalysisType>(&AnalysisType::ID); +} + +template<typename AnalysisType> +AnalysisType &Pass::getAnalysisID(AnalysisID PI) const { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver&&"Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(PI); + assert(ResultPass && + "getAnalysis*() called on an analysis that was not " + "'required' by pass!"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +/// getAnalysis<AnalysisType>() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +template<typename AnalysisType> +AnalysisType &Pass::getAnalysis(Function &F) { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID<AnalysisType>(&AnalysisType::ID, F); +} + +template<typename AnalysisType> +AnalysisType &Pass::getAnalysisID(AnalysisID PI, Function &F) { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver && "Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(this, PI, F); + assert(ResultPass && "Unable to find requested analysis info"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we use getAdjustedAnalysisPointer here to potentially + // adjust the return pointer (because the class may multiply inherit, once + // from pass, once from AnalysisType). + return *(AnalysisType*)ResultPass->getAdjustedAnalysisPointer(PI); +} + +} // end namespace llvm + +#endif // LLVM_PASSANALYSISSUPPORT_H |
