/* * The MIT License (MIT) * * Copyright (c) 2015-2022 Advanced Micro Devices, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace migraphx { inline namespace MIGRAPHX_INLINE_NS { MIGRAPHX_DECLARE_ENV_VAR(MIGRAPHX_TRACE_PASSES); void validate_pass(module& mod, const pass& p, tracer trace) { (void)mod; (void)p; (void)trace; #ifndef NDEBUG trace("Validate ..."); auto invalid = mod.validate(); if(invalid != mod.end()) { auto index = std::distance(mod.begin(), invalid); MIGRAPHX_THROW(p.name() + " pass produces invalid program at instruction " + std::to_string(index) + ": " + invalid->name()); } trace(); #endif } void run_pass(program& prog, const pass& p, tracer trace) { trace("Pass: ", p.name()); p.apply(prog); trace(prog); } struct module_pm : module_pass_manager { module* mod; program* prog; tracer* t; module_pm(module* pmod = nullptr, program* pprog = nullptr, tracer* pt = nullptr) : mod(pmod), prog(pprog), t(pt) { } template void trace(Ts&&... xs) const { assert(t); (*t)(xs...); } virtual module& get_module() override { assert(mod); return *mod; } virtual module* create_module(const std::string& name) override { assert(prog); return prog->create_module(name); } virtual void run_pass(const pass& p) override { assert(mod); trace("Module: ", mod->name(), ", Pass: ", p.name()); assert(mod->validate() == mod->end()); p.apply(*this); trace(*mod); validate_pass(*mod, p, *t); } }; module& get_module(module_pass_manager& mpm) { return mpm.get_module(); } void run_passes(module& mod, const std::vector& passes, tracer trace) { if(enabled(MIGRAPHX_TRACE_PASSES{})) trace = tracer{std::cout}; for(const auto& p : passes) { module_pm{&mod, nullptr, &trace}.run_pass(p); } } void run_passes(program& prog, const std::vector& passes, tracer trace) { if(enabled(MIGRAPHX_TRACE_PASSES{})) trace = tracer{std::cout}; for(const auto& p : passes) { auto mods = prog.get_modules(); for(const auto& mod : reverse(mods)) { if(mod->bypass()) continue; module_pm{mod, &prog, &trace}.run_pass(p); } run_pass(prog, p, trace); } } } // namespace MIGRAPHX_INLINE_NS } // namespace migraphx