+/// \brief An abstract set of preserved analyses following a transformation pass
+/// run.
+///
+/// When a transformation pass is run, it can return a set of analyses whose
+/// results were preserved by that transformation. The default set is "none",
+/// and preserving analyses must be done explicitly.
+///
+/// There is also an explicit all state which can be used (for example) when
+/// the IR is not mutated at all.
+class PreservedAnalyses {
+public:
+ /// \brief Convenience factory function for the empty preserved set.
+ static PreservedAnalyses none() { return PreservedAnalyses(); }
+
+ /// \brief Construct a special preserved set that preserves all passes.
+ static PreservedAnalyses all() {
+ PreservedAnalyses PA;
+ PA.PreservedPassIDs.insert((void *)AllPassesID);
+ return PA;
+ }
+
+ PreservedAnalyses &operator=(PreservedAnalyses Arg) {
+ swap(Arg);
+ return *this;
+ }
+
+ void swap(PreservedAnalyses &Arg) {
+ PreservedPassIDs.swap(Arg.PreservedPassIDs);
+ }
+
+ /// \brief Mark a particular pass as preserved, adding it to the set.
+ template <typename PassT> void preserve() {
+ if (!areAllPreserved())
+ PreservedPassIDs.insert(PassT::ID());
+ }
+
+ /// \brief Intersect this set with another in place.
+ ///
+ /// This is a mutating operation on this preserved set, removing all
+ /// preserved passes which are not also preserved in the argument.
+ void intersect(const PreservedAnalyses &Arg) {
+ if (Arg.areAllPreserved())
+ return;
+ if (areAllPreserved()) {
+ PreservedPassIDs = Arg.PreservedPassIDs;
+ return;
+ }
+ for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
+ E = PreservedPassIDs.end();
+ I != E; ++I)
+ if (!Arg.PreservedPassIDs.count(*I))
+ PreservedPassIDs.erase(*I);
+ }
+
+#if LLVM_HAS_RVALUE_REFERENCES
+ /// \brief Intersect this set with a temporary other set in place.
+ ///
+ /// This is a mutating operation on this preserved set, removing all
+ /// preserved passes which are not also preserved in the argument.
+ void intersect(PreservedAnalyses &&Arg) {
+ if (Arg.areAllPreserved())
+ return;
+ if (areAllPreserved()) {
+ PreservedPassIDs = std::move(Arg.PreservedPassIDs);
+ return;
+ }
+ for (SmallPtrSet<void *, 2>::const_iterator I = PreservedPassIDs.begin(),
+ E = PreservedPassIDs.end();
+ I != E; ++I)
+ if (!Arg.PreservedPassIDs.count(*I))
+ PreservedPassIDs.erase(*I);
+ }
+#endif
+
+ /// \brief Query whether a pass is marked as preserved by this set.
+ template <typename PassT> bool preserved() const {
+ return preserved(PassT::ID());
+ }
+
+ /// \brief Query whether an abstract pass ID is marked as preserved by this
+ /// set.
+ bool preserved(void *PassID) const {
+ return PreservedPassIDs.count((void *)AllPassesID) ||
+ PreservedPassIDs.count(PassID);
+ }
+
+private:
+ // Note that this must not be -1 or -2 as those are already used by the
+ // SmallPtrSet.
+ static const uintptr_t AllPassesID = (intptr_t)-3;
+
+ bool areAllPreserved() const { return PreservedPassIDs.count((void *)AllPassesID); }
+
+ SmallPtrSet<void *, 2> PreservedPassIDs;
+};
+
+inline void swap(PreservedAnalyses &LHS, PreservedAnalyses &RHS) {
+ LHS.swap(RHS);
+}
+