[llvm] r195241 - [PM] Add the preservation system to the new pass manager.
Duncan P. N. Exon Smith
dexonsmith at apple.com
Tue Jun 10 10:01:48 PDT 2014
ping
> On 2014 May 9, at 12:15, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote:
>
> On 2013-Nov-20, at 03:31, Chandler Carruth <chandlerc at gmail.com> wrote:
>
>> Author: chandlerc
>> Date: Wed Nov 20 05:31:50 2013
>> New Revision: 195241
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=195241&view=rev
>> Log:
>> [PM] Add the preservation system to the new pass manager.
>>
>> This adds a new set-like type which represents a set of preserved
>> analysis passes. The set is managed via the opaque PassT::ID() void*s.
>> The expected convenience templates for interacting with specific passes
>> are provided. It also supports a symbolic "all" state which is
>> represented by an invalid pointer in the set. This state is nicely
>> saturating as it comes up often. Finally, it supports intersection which
>> is used when finding the set of preserved passes after N different
>> transforms.
>>
>> The pass API is then changed to return the preserved set rather than
>> a bool. This is much more self-documenting than the previous system.
>> Returning "none" is a conservatively correct solution just like
>> returning "true" from todays passes and not marking any passes as
>> preserved. Passes can also be dynamically preserved or not throughout
>> the run of the pass, and whatever gets returned is the binding state.
>> Finally, preserving "all" the passes is allowed for no-op transforms
>> that simply can't harm such things.
>>
>> Finally, the analysis managers are changed to instead of blindly
>> invalidating all of the analyses, invalidate those which were not
>> preserved. This should rig up all of the basic preservation
>> functionality. This also correctly combines the preservation moving up
>> from one IR-layer to the another and the preservation aggregation across
>> N pass runs. Still to go is incrementally correct invalidation and
>> preservation across IR layers incrementally during N pass runs. That
>> will wait until we have a device for even exposing analyses across IR
>> layers.
>>
>> While the core of this change is obvious, I'm not happy with the current
>> testing, so will improve it to cover at least some of the invalidation
>> that I can test easily in a subsequent commit.
>>
>> Modified:
>> llvm/trunk/include/llvm/IR/PassManager.h
>> llvm/trunk/lib/IR/PassManager.cpp
>> llvm/trunk/unittests/IR/PassManagerTest.cpp
>>
>> Modified: llvm/trunk/include/llvm/IR/PassManager.h
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=195241&r1=195240&r2=195241&view=diff
>> ==============================================================================
>> --- llvm/trunk/include/llvm/IR/PassManager.h (original)
>> +++ llvm/trunk/include/llvm/IR/PassManager.h Wed Nov 20 05:31:50 2013
>> @@ -36,6 +36,7 @@
>> //===----------------------------------------------------------------------===//
>>
>> #include "llvm/ADT/DenseMap.h"
>> +#include "llvm/ADT/SmallPtrSet.h"
>> #include "llvm/ADT/polymorphic_ptr.h"
>> #include "llvm/Support/type_traits.h"
>> #include "llvm/IR/Function.h"
>> @@ -48,6 +49,106 @@ namespace llvm {
>> class Module;
>> class Function;
>>
>> +/// \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);
>
> Interesting that SmallPtrSet doesn't let you erase by iterator. Is
> that an API oversight, or is it intentional?
>
>> + }
>> +
>> +#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);
>> + }
>
> Shouldn't these functions be spelled "isPreserved()"?
>
>> +
>> +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);
>> +}
>> +
More information about the llvm-commits
mailing list