From 11a00b4ae2c9595579d23c10f4eb001e7eaa18cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roland=20Lei=C3=9Fa?= Date: Wed, 26 Oct 2022 14:53:29 +0200 Subject: [PATCH] just refactoring/simplifiny a couple of rewrite related things --- thorin/be/emitter.h | 3 +-- thorin/def.h | 1 - thorin/phase/phase.cpp | 9 +++----- thorin/phase/phase.h | 42 ++++++++++------------------------ thorin/rewrite.cpp | 51 ++++++++++++++++++++---------------------- thorin/rewrite.h | 46 ++++++++++++++++--------------------- 6 files changed, 59 insertions(+), 93 deletions(-) diff --git a/thorin/be/emitter.h b/thorin/be/emitter.h index 7f3345ba84..cb036a925a 100644 --- a/thorin/be/emitter.h +++ b/thorin/be/emitter.h @@ -13,8 +13,7 @@ class Emitter : public ScopePhase { constexpr const Child& child() const { return *static_cast(this); }; constexpr Child& child() { return *static_cast(this); }; - /// Integer wrapper for Emitter::emit that checks and retrieves/puts the `Value` from - /// Emitter::locals_/Emitter::globals_. + /// Internal wrapper for Emitter::emit that schedules @p def and invokes `child().emit_bb`. Value emit_(const Def* def) { auto place = scheduler_.smart(def); auto& bb = lam2bb_[place->as_nom()]; diff --git a/thorin/def.h b/thorin/def.h index 4e15fb7dbe..336674268c 100644 --- a/thorin/def.h +++ b/thorin/def.h @@ -357,7 +357,6 @@ class Def : public RuntimeCast { /// @name var ///@{ /// Retrieve Var for *nominals*. - const Var* var(const Def* dbg = {}); THORIN_PROJ(var, ) ///@} diff --git a/thorin/phase/phase.cpp b/thorin/phase/phase.cpp index 2fa621c3dc..8760160f31 100644 --- a/thorin/phase/phase.cpp +++ b/thorin/phase/phase.cpp @@ -2,9 +2,6 @@ namespace thorin { -std::pair PhaseRewriter::pre_rewrite(const Def* def) { return phase.pre_rewrite(def); } -std::pair PhaseRewriter::post_rewrite(const Def* def) { return phase.post_rewrite(def); } - void Phase::run() { world().ILOG("=== {}: start ===", name()); start(); @@ -12,10 +9,10 @@ void Phase::run() { } void RWPhase::start() { - for (const auto& [_, ax] : world().axioms()) rewrite(ax); - for (const auto& [_, nom] : world().externals()) rewrite(nom)->as_nom()->make_external(); + for (const auto& [_, ax] : old_world().axioms()) rewrite(ax); + for (const auto& [_, nom] : old_world().externals()) rewrite(nom)->as_nom()->make_external(); - swap(world_, new_world()); + swap(world_, new_world_); } void FPPhase::start() { diff --git a/thorin/phase/phase.h b/thorin/phase/phase.h index 7ecc4e3bb7..0dea75adba 100644 --- a/thorin/phase/phase.h +++ b/thorin/phase/phase.h @@ -47,52 +47,34 @@ class Phase { bool dirty_; }; -class RWPhase; - -class PhaseRewriter : public Rewriter { -public: - PhaseRewriter(RWPhase& phase, World& old_world, World& new_world) - : Rewriter(old_world, new_world) - , phase(phase) {} - - std::pair pre_rewrite(const Def*) override; - std::pair post_rewrite(const Def*) override; - - RWPhase& phase; -}; - -/// Visits the current Phase::world and constructs a new World Phase::new_world along the way. +/// Visits the current Phase::world and constructs a new RWPhase::world along the way. /// It recursively **rewrites** all World::externals(). class RWPhase : public Phase { public: - RWPhase(World& world, std::string_view name) - : Phase(world, name, false) - , new_world_(world.state()) - , rewriter_(*this, world, new_world_) {} + RWPhase(World& old_world, std::string_view name) + : Phase(old_world, name, false) + , new_world_(old_world.state()) + , rewriter_(new_world_) {} void start() override; /// @name getters ///@{ - const World& old_world() { return world(); } - World& new_world() { return new_world_; } - Def2Def& old2new() { return rewriter_.old2new; } + const World& old_world() { return world_; } + World& world() { return new_world_; } ///< RWPhase::new_world_ is the "default" world. + const Def* map(const Def* old_def, const Def* new_def) { return rewriter_.map(old_def, new_def); } ///@} /// @name rewrite ///@{ - - /// See thorin::Rewriter::rewrite. - const Def* rewrite(const Def* old_def) { return rewriter_.rewrite(old_def); } - /// See thorin::Rewriter::pre_rewrite. - virtual std::pair pre_rewrite(const Def*) { return {nullptr, false}; } - /// See thorin::Rewriter::post_rewrite. - virtual std::pair post_rewrite(const Def*) { return {nullptr, false}; } + virtual const Def* rewrite(const Def* old_def) { return rewriter_.rewrite(old_def); } + virtual const Def* rewrite_structural(const Def* old_def) { return rewriter_.rewrite_structural(old_def); } + virtual const Def* rewrite_nom(Def* old_nom) { return rewriter_.rewrite_nom(old_nom); } ///@} protected: World new_world_; - PhaseRewriter rewriter_; + Rewriter rewriter_; }; /// Removes unreachable and dead code by rebuilding the whole World into a new one and `swap`ping afterwards. diff --git a/thorin/rewrite.cpp b/thorin/rewrite.cpp index 03ab09b2a2..a24019d5c8 100644 --- a/thorin/rewrite.cpp +++ b/thorin/rewrite.cpp @@ -7,47 +7,44 @@ namespace thorin { const Def* Rewriter::rewrite(const Def* old_def) { - if (auto i = old2new.find(old_def); i != old2new.end()) return i->second; - - if (auto [pre, recurse] = pre_rewrite(old_def); pre) { - auto new_def = recurse ? rewrite(pre) : pre; - return old2new[pre] = new_def; - } - - auto new_type = old_def->type() ? rewrite(old_def->type()) : nullptr; - auto new_dbg = old_def->dbg() ? rewrite(old_def->dbg()) : nullptr; + if (!old_def) return nullptr; + if (old_def->isa()) return world().univ(); + if (auto i = old2new_.find(old_def); i != old2new_.end()) return i->second; if (auto infer = old_def->isa_nom()) { if (auto op = infer->op()) return rewrite(op); } - if (auto old_nom = old_def->isa_nom()) { - auto new_nom = old_nom->stub(new_world, new_type, new_dbg); - old2new[old_nom] = new_nom; - - for (size_t i = 0, e = old_nom->num_ops(); i != e; ++i) { - if (auto old_op = old_nom->op(i)) new_nom->set(i, rewrite(old_op)); - } - - if (auto new_def = new_nom->restructure()) return old2new[old_nom] = new_def; + if (auto old_nom = old_def->isa_nom()) return rewrite_nom(old_nom); - return new_nom; - } + auto new_def = rewrite_structural(old_def); + return map(old_def, new_def); +} +const Def* Rewriter::rewrite_structural(const Def* old_def) { + auto new_type = rewrite(old_def->type()); + auto new_dbg = rewrite(old_def->dbg()); DefArray new_ops(old_def->num_ops(), [&](auto i) { return rewrite(old_def->op(i)); }); - auto new_def = old_def->rebuild(new_world, new_type, new_ops, new_dbg); + return old_def->rebuild(world(), new_type, new_ops, new_dbg); +} + +const Def* Rewriter::rewrite_nom(Def* old_nom) { + auto new_type = rewrite(old_nom->type()); + auto new_dbg = rewrite(old_nom->dbg()); + auto new_nom = old_nom->stub(world(), new_type, new_dbg); + map(old_nom, new_nom); - if (auto [post, recurse] = post_rewrite(new_def); post) { - auto new_def = recurse ? rewrite(post) : post; - return old2new[post] = new_def; + for (size_t i = 0, e = old_nom->num_ops(); i != e; ++i) { + if (auto old_op = old_nom->op(i)) new_nom->set(i, rewrite(old_op)); } - return old2new[old_def] = new_def; + if (auto new_def = new_nom->restructure()) return map(old_nom, new_def); + return new_nom; } const Def* rewrite(const Def* def, const Def* old_def, const Def* new_def, const Scope& scope) { ScopeRewriter rewriter(def->world(), scope); - rewriter.old2new[old_def] = new_def; + rewriter.map(old_def, new_def); return rewriter.rewrite(def); } @@ -62,7 +59,7 @@ const Def* rewrite(Def* nom, const Def* arg, size_t i) { DefArray rewrite(Def* nom, const Def* arg, const Scope& scope) { ScopeRewriter rewriter(nom->world(), scope); - rewriter.old2new[nom->var()] = arg; + rewriter.map(nom->var(), arg); return DefArray(nom->num_ops(), [&](size_t i) { return rewriter.rewrite(nom->op(i)); }); } diff --git a/thorin/rewrite.h b/thorin/rewrite.h index 498f0f18c6..163b5f84cf 100644 --- a/thorin/rewrite.h +++ b/thorin/rewrite.h @@ -6,51 +6,43 @@ namespace thorin { -/// Rewrites part of a program. +/// Recurseivly rewrites part of a program **into** the provided World. +/// This World may be different than the World we started with. class Rewriter { public: - Rewriter(World& old_world, World& new_world) - : old_world(old_world) - , new_world(new_world) { - old2new[old_world.univ()] = new_world.univ(); - } Rewriter(World& world) - : Rewriter(world, world) {} + : world_(world) {} - /// @name rewrite - ///@{ + World& world() { return world_; } - /// Recursively rewrites @p old_def. - /// Invokes Rewriter::pre_rewrite at the beginning and Rewriter::post_rewrite at the end. - virtual const Def* rewrite(const Def* old_def); - - /// Rewrite a given Def in pre-order. - /// @return - /// * `{nullptr, false}` to do nothing - /// * `{new_def, false}` to return `new_def` **without** recursing on `new_def` again - /// * `{new_def, true}` to return `new_def` **with** recursing on `new_def` again - virtual std::pair pre_rewrite(const Def*) { return {nullptr, false}; } - /// As above but in post-order. - virtual std::pair post_rewrite(const Def*) { return {nullptr, false}; } + /// @name recursively rewrite old Defs + ///@{ + const Def* map(const Def* old_def, const Def* new_def) { return old2new_[old_def] = new_def; } + virtual const Def* rewrite(const Def*); + virtual const Def* rewrite_structural(const Def*); + virtual const Def* rewrite_nom(Def*); ///@} - World& old_world; - World& new_world; - Def2Def old2new; +private: + World& world_; + Def2Def old2new_; }; class ScopeRewriter : public Rewriter { public: ScopeRewriter(World& world, const Scope& scope) : Rewriter(world) - , scope(scope) {} + , scope_(scope) {} + + const Scope& scope() const { return scope_; } const Def* rewrite(const Def* old_def) override { - if (!scope.bound(old_def)) return old_def; + if (!old_def || !scope().bound(old_def)) return old_def; return Rewriter::rewrite(old_def); } - const Scope& scope; +private: + const Scope& scope_; }; /// Rewrites @p def by mapping @p old_def to @p new_def while obeying @p scope.