Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/default-compilation' into ho_cod…
Browse files Browse the repository at this point in the history
…egen
  • Loading branch information
NeuralCoder3 committed Dec 6, 2022
2 parents 87b6356 + 7269d64 commit fb1ec79
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 106 deletions.
7 changes: 4 additions & 3 deletions dialects/compile/compile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ void add_passes(World& world, PipelineBuilder& builder, Passes& passes, DefVec&
// This pass then calls the registered passes in the order they were registered in the last phase.

// We create a new dummy phase in which the passes should be inserted.
builder.append_phase_end([](Pipeline&) {});

// builder.append_phase_end([](Pipeline&) {});
builder.begin_pass_phase();
for (auto pass : pass_list) { compile::handle_optimization_part(pass, world, passes, builder); }
builder.end_pass_phase();
}

extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
Expand All @@ -44,7 +45,7 @@ extern "C" THORIN_EXPORT thorin::DialectInfo thorin_get_dialect_info() {
world.DLOG("Generate debug_phase: {}", app);
int level = (int)(app->as<App>()->arg(0)->as<Lit>()->get<u64>());
world.DLOG(" Level: {}", level);
builder.append_pass_after_end([=](PassMan& man) { man.add<thorin::compile::DebugPrint>(level); });
builder.add_phase<compile::DebugPrint>(level);
};

passes[flags_t(Axiom::Base<thorin::compile::passes_to_phase>)] =
Expand Down
9 changes: 4 additions & 5 deletions thorin/pass/optimize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void optimize(World& world, Passes& passes, std::vector<Dialect>& dialects) {
// But the compile dialect has not the necessary communication pipeline.
// Therefore, we register the handlers and let the compile dialect call them.

PipelineBuilder pipe_builder;
PipelineBuilder pipe_builder(world);
// TODO: remove indirections of pipeline builder. Just add passes and phases directly to the pipeline.
for (auto& dialect : dialects) { pipe_builder.register_dialect(dialect); }

Expand All @@ -63,13 +63,12 @@ void optimize(World& world, Passes& passes, std::vector<Dialect>& dialects) {
auto pipeline_axiom = ax->as<Axiom>();
auto pipeline_flags = pipeline_axiom->flags();
assert(passes.contains(pipeline_flags));
world.DLOG("Building pipeline");
passes[pipeline_flags](world, pipe_builder, pipeline);

Pipeline pipe(world);
world.DLOG("Building pipeline");
pipe_builder.buildPipeline(pipe);
world.DLOG("Executing pipeline");
pipe_builder.run_pipeline();

pipe.run();
return;
}

Expand Down
79 changes: 16 additions & 63 deletions thorin/pass/pipelinebuilder.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include "thorin/pass/pipelinebuilder.h"

#include <compare>
// #include <compare>

#include <vector>
// #include <memory>
// #include <vector>

#include "thorin/def.h"
#include "thorin/dialects.h"
Expand All @@ -12,9 +13,11 @@
#include "thorin/pass/fp/eta_exp.h"
#include "thorin/pass/fp/eta_red.h"
#include "thorin/pass/fp/tail_rec_elim.h"
#include "thorin/pass/pass.h"
#include "thorin/pass/rw/partial_eval.h"
#include "thorin/pass/rw/ret_wrap.h"
#include "thorin/pass/rw/scalarize.h"
#include "thorin/phase/phase.h"

#include "dialects/mem/passes/fp/copy_prop.h"
#include "dialects/mem/passes/fp/ssa_constr.h"
Expand All @@ -23,77 +26,27 @@

namespace thorin {

void PipelineBuilder::remember_pass_instance(Pass* p, const Def* def) { pass_instances_[def] = p; }
Pass* PipelineBuilder::get_pass_instance(const Def* def) { return pass_instances_[def]; }

int PipelineBuilder::last_phase() {
auto phase_ids = phases();
auto max_phase_id = std::max_element(phase_ids.begin(), phase_ids.end());
auto max_phase = max_phase_id == phase_ids.end() ? 0 : *max_phase_id;
return max_phase;
}

void PipelineBuilder::append_phase_end(PhaseBuilder phase) { append_phase(last_phase() + 1, phase); }
void PipelineBuilder::append_pass_in_end(PassBuilder pass) { extend_opt_phase(last_phase(), pass); }
void PipelineBuilder::append_pass_after_end(PassBuilder pass) { extend_opt_phase(last_phase() + 1, pass); }

void PipelineBuilder::append_phase(int i, PhaseBuilder extension) {
if (!phase_extensions_.contains(i)) { phase_extensions_[i] = PhaseList(); }
phase_extensions_[i].push_back(extension);
}

void PipelineBuilder::extend_opt_phase(int i, PassBuilder extension) {
// adds extension to the i-th optimization phase
// if the ith phase does not exist, it is created
if (!pass_extensions_.contains(i)) { pass_extensions_[i] = std::vector<PrioPassBuilder>(); }
pass_extensions_[i].push_back(extension);
}

std::vector<int> PipelineBuilder::passes() {
std::vector<int> keys;
for (auto iter = pass_extensions_.begin(); iter != pass_extensions_.end(); iter++) { keys.push_back(iter->first); }
std::ranges::stable_sort(keys);
return keys;
}

std::vector<int> PipelineBuilder::phases() {
std::vector<int> keys;
for (auto iter = pass_extensions_.begin(); iter != pass_extensions_.end(); iter++) { keys.push_back(iter->first); }
for (auto iter = phase_extensions_.begin(); iter != phase_extensions_.end(); iter++) {
keys.push_back(iter->first);
}
std::ranges::stable_sort(keys);
// erase duplicates to avoid duplicating phases
keys.erase(std::unique(keys.begin(), keys.end()), keys.end());
return keys;
}

std::unique_ptr<PassMan> PipelineBuilder::opt_phase(int i, World& world) {
auto man = std::make_unique<PassMan>(world);

for (const auto& ext : pass_extensions_[i]) { ext(*man); }

return man;
void PipelineBuilder::remember_pass_instance(Pass* p, const Def* def) {
def->world().DLOG("associating {} with {}", def->gid(), p);
pass_instances_[def] = p;
}
Pass* PipelineBuilder::get_pass_instance(const Def* def) { return pass_instances_[def]; }

void PipelineBuilder::buildPipeline(Pipeline& pipeline) {
for (auto i : phases()) { buildPipelinePart(i, pipeline); }
}
void PipelineBuilder::buildPipelinePart(int i, Pipeline& pipeline) {
if (pass_extensions_.contains(i)) { pipeline.add<PassManPhase>(opt_phase(i, pipeline.world())); }

if (phase_extensions_.contains(i)) {
for (const auto& ext : phase_extensions_[i]) { ext(pipeline); }
}
void PipelineBuilder::begin_pass_phase() { man = std::make_unique<PassMan>(world_); }
void PipelineBuilder::end_pass_phase() {
std::unique_ptr<thorin::PassMan>&& pass_man_ref = std::move(man);
pipe->add<PassManPhase>(std::move(pass_man_ref));
man = nullptr;
}

void PipelineBuilder::register_dialect(Dialect& dialect) { dialects_.push_back(&dialect); }

bool PipelineBuilder::is_registered_dialect(std::string name) {
for (auto& dialect : dialects_) {
if (dialect->name() == name) { return true; }
}
return false;
}

void PipelineBuilder::run_pipeline() { pipe->run(); }

} // namespace thorin
60 changes: 25 additions & 35 deletions thorin/pass/pipelinebuilder.h
Original file line number Diff line number Diff line change
@@ -1,65 +1,53 @@
#pragma once

#include <functional>
#include <string>
#include <vector>
#include "thorin/world.h"

#include "thorin/pass/optimize.h"
#include "thorin/pass/pass.h"
#include "thorin/phase/phase.h"

namespace thorin {

using PassBuilder = std::function<void(PassMan&)>;
using PhaseBuilder = std::function<void(Pipeline&)>;
using PrioPassBuilder = PassBuilder;
using PrioPhaseBuilder = PhaseBuilder;
using PassList = std::vector<PrioPassBuilder>;
using PhaseList = std::vector<PrioPhaseBuilder>;
using PassInstanceMap = absl::btree_map<const Def*, Pass*, GIDLt<const Def*>>;
using PassInstanceMap = absl::btree_map<const Def*, Pass*, GIDLt<const Def*>>;

class PipelineBuilder {
public:
explicit PipelineBuilder() {}

int last_phase();
PipelineBuilder(World& world)
: world_(world) {
pipe = std::make_unique<Pipeline>(world);
man = nullptr;
}

// Adds a pass and remembers it associated with the given def.
template<class P, class... Args>
void add_pass(const Def* def, Args&&... args) {
append_pass_in_end([&, def, ... args = std::forward<Args>(args)](PassMan& man) {
auto pass = (Pass*)man.add<P>(args...);
remember_pass_instance(pass, def);
});
auto pass = (Pass*)man->add<P>(std::forward<Args>(args)...);
remember_pass_instance(pass, def);
}
template<class P, class... Args>
void add_phase(Args&&... args) {
assert(!man && "cannot add phase while in pass phase");
pipe->add<P>(std::forward<Args>(args)...);
}

void begin_pass_phase();
void end_pass_phase();

void remember_pass_instance(Pass* p, const Def*);
Pass* get_pass_instance(const Def*);
void append_phase_end(PhaseBuilder);
void append_pass_in_end(PassBuilder);

void append_pass_after_end(PassBuilder);

void append_phase(int i, PhaseBuilder);
void extend_opt_phase(int i, PassBuilder);

std::unique_ptr<PassMan> opt_phase(int i, World& world);
void buildPipeline(Pipeline& pipeline);
void buildPipelinePart(int i, Pipeline& pipeline);
void add_opt(PassMan man);

std::vector<int> passes();
std::vector<int> phases();

void register_dialect(Dialect& d);
bool is_registered_dialect(std::string name);

void run_pipeline();

private:
std::map<int, PassList> pass_extensions_;
std::map<int, PhaseList> phase_extensions_;
std::set<std::string> registered_dialects_;
std::vector<Dialect*> dialects_;
PassInstanceMap pass_instances_;
std::unique_ptr<PassMan> man;
std::unique_ptr<Pipeline> pipe;
World& world_;
};

template<class A, class P, class... CArgs>
Expand All @@ -72,8 +60,10 @@ void register_pass(Passes& passes, CArgs&&... args) {

template<class A, class P, class Q>
void register_pass_with_arg(Passes& passes) {
passes[flags_t(Axiom::Base<A>)] = [](World&, PipelineBuilder& builder, const Def* app) {
passes[flags_t(Axiom::Base<A>)] = [](World& world, PipelineBuilder& builder, const Def* app) {
auto pass_arg = (Q*)(builder.get_pass_instance(app->as<App>()->arg()));
world.DLOG("register using arg: {} of type {} for gid {}", pass_arg, typeid(Q).name(),
app->as<App>()->arg()->gid());
builder.add_pass<P>(app, pass_arg);
};
}
Expand Down

0 comments on commit fb1ec79

Please sign in to comment.