diff --git a/dialects/compile/compile.cpp b/dialects/compile/compile.cpp index 82b7855940..bf497d3587 100644 --- a/dialects/compile/compile.cpp +++ b/dialects/compile/compile.cpp @@ -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() { @@ -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()->arg(0)->as()->get()); world.DLOG(" Level: {}", level); - builder.append_pass_after_end([=](PassMan& man) { man.add(level); }); + builder.add_phase(level); }; passes[flags_t(Axiom::Base)] = diff --git a/thorin/pass/optimize.cpp b/thorin/pass/optimize.cpp index c6c253582d..b330dae725 100644 --- a/thorin/pass/optimize.cpp +++ b/thorin/pass/optimize.cpp @@ -52,7 +52,7 @@ void optimize(World& world, Passes& passes, std::vector& 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); } @@ -63,13 +63,12 @@ void optimize(World& world, Passes& passes, std::vector& dialects) { auto pipeline_axiom = ax->as(); 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; } diff --git a/thorin/pass/pipelinebuilder.cpp b/thorin/pass/pipelinebuilder.cpp index d92fd2e2f3..58e75b9fa1 100644 --- a/thorin/pass/pipelinebuilder.cpp +++ b/thorin/pass/pipelinebuilder.cpp @@ -1,8 +1,9 @@ #include "thorin/pass/pipelinebuilder.h" -#include +// #include -#include +// #include +// #include #include "thorin/def.h" #include "thorin/dialects.h" @@ -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" @@ -23,72 +26,20 @@ 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(); } - pass_extensions_[i].push_back(extension); -} - -std::vector PipelineBuilder::passes() { - std::vector 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 PipelineBuilder::phases() { - std::vector 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 PipelineBuilder::opt_phase(int i, World& world) { - auto man = std::make_unique(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(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(world_); } +void PipelineBuilder::end_pass_phase() { + std::unique_ptr&& pass_man_ref = std::move(man); + pipe->add(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; } @@ -96,4 +47,6 @@ bool PipelineBuilder::is_registered_dialect(std::string name) { return false; } +void PipelineBuilder::run_pipeline() { pipe->run(); } + } // namespace thorin diff --git a/thorin/pass/pipelinebuilder.h b/thorin/pass/pipelinebuilder.h index 6d88bc36eb..ddc1418648 100644 --- a/thorin/pass/pipelinebuilder.h +++ b/thorin/pass/pipelinebuilder.h @@ -1,8 +1,6 @@ #pragma once -#include -#include -#include +#include "thorin/world.h" #include "thorin/pass/optimize.h" #include "thorin/pass/pass.h" @@ -10,56 +8,46 @@ namespace thorin { -using PassBuilder = std::function; -using PhaseBuilder = std::function; -using PrioPassBuilder = PassBuilder; -using PrioPhaseBuilder = PhaseBuilder; -using PassList = std::vector; -using PhaseList = std::vector; -using PassInstanceMap = absl::btree_map>; +using PassInstanceMap = absl::btree_map>; class PipelineBuilder { public: - explicit PipelineBuilder() {} - - int last_phase(); + PipelineBuilder(World& world) + : world_(world) { + pipe = std::make_unique(world); + man = nullptr; + } // Adds a pass and remembers it associated with the given def. template void add_pass(const Def* def, Args&&... args) { - append_pass_in_end([&, def, ... args = std::forward(args)](PassMan& man) { - auto pass = (Pass*)man.add

(args...); - remember_pass_instance(pass, def); - }); + auto pass = (Pass*)man->add

(std::forward(args)...); + remember_pass_instance(pass, def); } + template + void add_phase(Args&&... args) { + assert(!man && "cannot add phase while in pass phase"); + pipe->add

(std::forward(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 opt_phase(int i, World& world); - void buildPipeline(Pipeline& pipeline); - void buildPipelinePart(int i, Pipeline& pipeline); - void add_opt(PassMan man); - - std::vector passes(); - std::vector phases(); void register_dialect(Dialect& d); bool is_registered_dialect(std::string name); + void run_pipeline(); + private: - std::map pass_extensions_; - std::map phase_extensions_; std::set registered_dialects_; std::vector dialects_; PassInstanceMap pass_instances_; + std::unique_ptr man; + std::unique_ptr pipe; + World& world_; }; template @@ -72,8 +60,10 @@ void register_pass(Passes& passes, CArgs&&... args) { template void register_pass_with_arg(Passes& passes) { - passes[flags_t(Axiom::Base)] = [](World&, PipelineBuilder& builder, const Def* app) { + passes[flags_t(Axiom::Base)] = [](World& world, PipelineBuilder& builder, const Def* app) { auto pass_arg = (Q*)(builder.get_pass_instance(app->as()->arg())); + world.DLOG("register using arg: {} of type {} for gid {}", pass_arg, typeid(Q).name(), + app->as()->arg()->gid()); builder.add_pass

(app, pass_arg); }; }