Skip to content

Commit

Permalink
just refactoring/simplifiny a couple of rewrite related things
Browse files Browse the repository at this point in the history
  • Loading branch information
leissa committed Oct 26, 2022
1 parent 6ff3037 commit 11a00b4
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 93 deletions.
3 changes: 1 addition & 2 deletions thorin/be/emitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ class Emitter : public ScopePhase {
constexpr const Child& child() const { return *static_cast<const Child*>(this); };
constexpr Child& child() { return *static_cast<Child*>(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<Lam>()];
Expand Down
1 change: 0 additions & 1 deletion thorin/def.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,6 @@ class Def : public RuntimeCast<Def> {
/// @name var
///@{
/// Retrieve Var for *nominals*.

const Var* var(const Def* dbg = {});
THORIN_PROJ(var, )
///@}
Expand Down
9 changes: 3 additions & 6 deletions thorin/phase/phase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,17 @@

namespace thorin {

std::pair<const Def*, bool> PhaseRewriter::pre_rewrite(const Def* def) { return phase.pre_rewrite(def); }
std::pair<const Def*, bool> PhaseRewriter::post_rewrite(const Def* def) { return phase.post_rewrite(def); }

void Phase::run() {
world().ILOG("=== {}: start ===", name());
start();
world().ILOG("=== {}: done ===", name());
}

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() {
Expand Down
42 changes: 12 additions & 30 deletions thorin/phase/phase.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const Def*, bool> pre_rewrite(const Def*) override;
std::pair<const Def*, bool> 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<const Def*, bool> pre_rewrite(const Def*) { return {nullptr, false}; }
/// See thorin::Rewriter::post_rewrite.
virtual std::pair<const Def*, bool> 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.
Expand Down
51 changes: 24 additions & 27 deletions thorin/rewrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<Univ>()) return world().univ();
if (auto i = old2new_.find(old_def); i != old2new_.end()) return i->second;

if (auto infer = old_def->isa_nom<Infer>()) {
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);
}

Expand All @@ -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)); });
}

Expand Down
46 changes: 19 additions & 27 deletions thorin/rewrite.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const Def*, bool> pre_rewrite(const Def*) { return {nullptr, false}; }
/// As above but in post-order.
virtual std::pair<const Def*, bool> 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.
Expand Down

0 comments on commit 11a00b4

Please sign in to comment.