#include "manager.h" #include #include #include "pass.h" #include "sir/analyze/analysis.h" #include "sir/analyze/dataflow/cfg.h" #include "sir/analyze/dataflow/reaching.h" #include "sir/analyze/module/global_vars.h" #include "sir/analyze/module/side_effect.h" #include "sir/transform/folding/folding.h" #include "sir/transform/lowering/imperative.h" #include "sir/transform/lowering/pipeline.h" #include "sir/transform/manager.h" #include "sir/transform/parallel/openmp.h" #include "sir/transform/pythonic/dict.h" #include "sir/transform/pythonic/io.h" #include "sir/transform/pythonic/str.h" #include "util/common.h" namespace seq { namespace ir { namespace transform { const int PassManager::PASS_IT_MAX = 5; std::string PassManager::KeyManager::getUniqueKey(const std::string &key) { // make sure we can't ever produce duplicate "unique'd" keys seqassert(key.find(':') == std::string::npos, "pass key '{}' contains invalid character ':'", key); auto it = keys.find(key); if (it == keys.end()) { keys.emplace(key, 1); return key; } else { auto id = ++(it->second); return key + ":" + std::to_string(id); } } std::string PassManager::registerPass(std::unique_ptr pass, const std::string &insertBefore, std::vector reqs, std::vector invalidates) { std::string key = pass->getKey(); if (isDisabled(key)) return ""; key = km.getUniqueKey(key); for (const auto &req : reqs) { assert(deps.find(req) != deps.end()); deps[req].push_back(key); } passes.insert(std::make_pair( key, PassMetadata(std::move(pass), std::move(reqs), std::move(invalidates)))); passes[key].pass->setManager(this); if (insertBefore.empty()) { executionOrder.push_back(key); } else { auto it = std::find(executionOrder.begin(), executionOrder.end(), insertBefore); seqassert(it != executionOrder.end(), "pass with key '{}' not found in manager", insertBefore); executionOrder.insert(it, key); } return key; } std::string PassManager::registerAnalysis(std::unique_ptr analysis, std::vector reqs) { std::string key = analysis->getKey(); if (isDisabled(key)) return ""; key = km.getUniqueKey(key); for (const auto &req : reqs) { assert(deps.find(req) != deps.end()); deps[req].push_back(key); } analyses.insert( std::make_pair(key, AnalysisMetadata(std::move(analysis), std::move(reqs)))); analyses[key].analysis->setManager(this); deps[key] = {}; return key; } void PassManager::run(Module *module) { for (auto &p : executionOrder) { runPass(module, p); } } void PassManager::runPass(Module *module, const std::string &name) { auto &meta = passes[name]; auto run = true; auto it = 0; while (run && it < PASS_IT_MAX) { for (auto &dep : meta.reqs) { runAnalysis(module, dep); } meta.pass->run(module); for (auto &inv : meta.invalidates) invalidate(inv); ++it; run = meta.pass->shouldRepeat(); } } void PassManager::runAnalysis(Module *module, const std::string &name) { if (results.find(name) != results.end()) return; auto &meta = analyses[name]; for (auto &dep : meta.reqs) { runAnalysis(module, dep); } results[name] = meta.analysis->run(module); } void PassManager::invalidate(const std::string &key) { std::unordered_set open = {key}; while (!open.empty()) { std::unordered_set newOpen; for (const auto &k : open) { if (results.find(k) != results.end()) { results.erase(k); newOpen.insert(deps[k].begin(), deps[k].end()); } } open = std::move(newOpen); } } void PassManager::registerStandardPasses(bool debug) { if (debug) { registerPass(std::make_unique()); registerPass(std::make_unique()); registerPass(std::make_unique()); } else { // Pythonic registerPass(std::make_unique()); registerPass(std::make_unique()); registerPass(std::make_unique()); // lowering registerPass(std::make_unique()); registerPass(std::make_unique()); // folding auto seKey1 = registerAnalysis(std::make_unique( /*globalAssignmentHasSideEffects=*/true)); auto seKey2 = registerAnalysis(std::make_unique( /*globalAssignmentHasSideEffects=*/false)); auto cfgKey = registerAnalysis(std::make_unique()); auto rdKey = registerAnalysis( std::make_unique(cfgKey), {cfgKey}); auto globalKey = registerAnalysis(std::make_unique()); registerPass(std::make_unique( seKey1, rdKey, globalKey, /*runGlobalDemoton=*/false), /*insertBefore=*/"", {seKey1, rdKey, globalKey}, {seKey1, rdKey, cfgKey, globalKey}); // parallel registerPass(std::make_unique()); registerPass(std::make_unique(seKey2, rdKey, globalKey, /*runGlobalDemoton=*/true), /*insertBefore=*/"", {seKey2, rdKey, globalKey}, {seKey2, rdKey, cfgKey, globalKey}); } } } // namespace transform } // namespace ir } // namespace seq