32 std::string_view
name()
const {
return name_; }
33 size_t index()
const {
return index_; }
92 virtual void*
alloc() {
return nullptr; }
93 virtual void*
copy(
const void*) {
return nullptr; }
115 const auto&
passes()
const {
return passes_; }
126 template<
class P,
class... Args> P*
add(Args&&... args) {
127 auto key = std::type_index(
typeid(P));
128 if (
auto it = registry_.find(key); it != registry_.end())
return static_cast<P*
>(it->second);
129 auto p = std::make_unique<P>(*
this, std::forward<Args>(args)...);
131 fixed_point_ |= res->fixed_point();
132 passes_.emplace_back(std::move(p));
133 registry_.emplace(key, res);
138 template<
class P,
class... Args>
static void run(
World&
world, Args&&... args) {
140 man.
add<P>(std::forward<Args>(args)...);
150 State(
const State&) =
delete;
151 State(State&&) =
delete;
152 State& operator=(State) =
delete;
156 Def* curr_mut =
nullptr;
158 std::stack<Def*> stack;
159 MutMap<undo_t> mut2visit;
166 void pop_states(
undo_t undo);
167 State& curr_state() {
168 assert(!states_.empty());
169 return states_.back();
171 const State& curr_state()
const {
172 assert(!states_.empty());
173 return states_.back();
175 undo_t curr_undo()
const {
return states_.size() - 1; }
182 Ref map(Ref old_def, Ref new_def) {
183 curr_state().old2new[old_def] = new_def;
184 curr_state().old2new.emplace(new_def, new_def);
188 std::optional<Ref> lookup(Ref old_def) {
189 for (
auto& state : states_ | std::ranges::views::reverse)
190 if (
auto i = state.old2new.find(old_def); i != state.old2new.end())
return i->second;
198 bool analyzed(Ref def) {
199 for (
auto& state : states_ | std::ranges::views::reverse)
200 if (state.analyzed.contains(def))
return true;
201 curr_state().analyzed.emplace(def);
207 std::deque<std::unique_ptr<Pass>> passes_;
208 absl::flat_hash_map<std::type_index, Pass*> registry_;
209 std::deque<State> states_;
210 Def* curr_mut_ =
nullptr;
211 bool fixed_point_ =
false;
214 template<
class P,
class M>
friend class FPPass;
226 if constexpr (std::is_same<M, Def>::value)
233 if constexpr (std::is_same<M, Def>::value)
258 assert(!
states().empty());
263 template<
class K>
auto&
data(
const K& key) {
return data()[key]; }
265 template<
size_t I,
class K>
auto&
data(
const K& key) {
return data<I>()[key]; }
274 const auto& mut2visit =
Super::man().curr_state().mut2visit;
275 if (
auto i = mut2visit.find(mut); i != mut2visit.end())
return i->second;
281 for (
auto i =
states().size(); i-- != 0;)
290 void*
alloc()
override {
return new typename P::Data(); }
291 void*
copy(
const void* p)
override {
return new typename P::Data(*
static_cast<const typename P::Data*
>(p)); }
292 void dealloc(
void* state)
override {
delete static_cast<typename P::Data*
>(state); }
Inherit from this class using CRTP, if you do need a Pass with a state and a fixed-point.
void dealloc(void *state) override
Destructor.
undo_t undo_visit(Def *mut) const
Retrieves the point to backtrack to just before mut was seen the very first time.
auto & data(const K &key)
Use this for your convenience if P::Data is a map.
FPPass(PassMan &man, std::string_view name)
void * copy(const void *p) override
Copy constructor.
undo_t curr_undo() const
Current undo point.
const auto & states() const
bool fixed_point() const override
std::tuple<> Data
Default.
void * alloc() override
Default constructor.
auto & data(const K &key)
Use this for your convenience if P::Data<I> is a map.
undo_t undo_enter(Def *mut) const
Retrieves the point to backtrack to just before rewriting mut's body.
An optimizer that combines several optimizations in an optimal way.
void run()
Run all registered passes on the whole World.
static void run(World &world, Args &&... args)
Runs a single Pass.
const auto & passes() const
P * add(Args &&... args)
Add a pass to this PassMan.
All Passes that want to be registered in the PassMan must implement this interface.
virtual void enter()
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
virtual undo_t analyze(const Proxy *)
const PassMan & man() const
virtual Ref rewrite(const Proxy *proxy)
virtual Ref rewrite(Ref def)
Pass(PassMan &, std::string_view name)
virtual void * alloc()
Default constructor.
const Proxy * isa_proxy(Ref def, u32 tag=0)
Check whether given def is a Proxy whose Proxy::pass matches this Pass's IPass::index.
virtual void dealloc(void *)
Destructor.
virtual undo_t analyze(const Var *)
const Proxy * as_proxy(Ref def, u32 tag=0)
virtual void prepare()
Invoked once before entering the main rewrite loop.
virtual void * copy(const void *)
Copy constructor.
virtual undo_t analyze(Ref)
virtual bool fixed_point() const
virtual bool inspect() const =0
Should the PassMan even consider this pass?
virtual Ref rewrite(const Var *var)
std::string_view name() const
const Proxy * proxy(Ref type, Defs ops, u32 tag=0)
u32 pass() const
IPass::index within PassMan.
Inherit from this class using CRTP, if your Pass does not need state and a fixed-point iteration.
RWPass(PassMan &man, std::string_view name)
bool inspect() const override
Should the PassMan even consider this pass?
Helper class to retrieve Infer::arg if present.
This is a thin wrapper for std::span<T, N> with the following additional features:
The World represents the whole program and manages creation of MimIR nodes (Defs).
const Proxy * proxy(Ref type, Defs ops, u32 index, u32 tag)
DefMap< const Def * > Def2Def
Vector< const Def * > DefVec
GIDSet< const Def * > DefSet
static constexpr undo_t No_Undo
constexpr decltype(auto) get(mim::Span< T, N > span)