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());
261 template<
size_t I>
auto&
data() {
return std::get<I>(
data()); }
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.
std::tuple<> Data
Default.
void * alloc() override
Default constructor.
undo_t curr_undo() const
Current undo point.
undo_t undo_visit(Def *mut) const
Retrieves the point to backtrack to just before mut was seen the very first time.
void * copy(const void *p) override
Copy constructor.
const auto & states() const
bool fixed_point() const override
auto & data(const K &key)
Use this for your convenience if P::Data<I> is a map.
FPPass(PassMan &man, std::string_view name)
void dealloc(void *state) override
Destructor.
auto & data(const K &key)
Use this for your convenience if P::Data 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.
const auto & passes() const
P * add(Args &&... args)
Add a pass to this PassMan.
void run()
Run all registered passes on the whole World.
static void run(World &world, Args &&... args)
Runs a single Pass.
All Passes that want to be registered in the PassMan must implement this interface.
virtual bool inspect() const =0
Should the PassMan even consider this pass?
virtual void prepare()
Invoked once before entering the main rewrite loop.
virtual undo_t analyze(Ref)
virtual Ref rewrite(const Var *var)
virtual undo_t analyze(const Var *)
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 undo_t analyze(const Proxy *)
virtual void enter()
Invoked just before Pass::rewriteing PassMan::curr_mut's body.
const PassMan & man() const
virtual void dealloc(void *)
Destructor.
virtual void * alloc()
Default constructor.
virtual void * copy(const void *)
Copy constructor.
const Proxy * as_proxy(Ref def, u32 tag=0)
virtual Ref rewrite(Ref def)
virtual bool fixed_point() const
std::string_view name() const
const Proxy * proxy(Ref type, Defs ops, u32 tag=0)
virtual Ref rewrite(const Proxy *proxy)
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 Thorin nodes (Defs).
const Proxy * proxy(Ref type, Defs ops, u32 index, u32 tag)
static constexpr undo_t No_Undo
DefMap< const Def * > Def2Def
GIDSet< const Def * > DefSet
Value * find(IndexMap< Indexer, Key, Value * > &map, Key key)
Vector< const Def * > DefVec