diff --git a/src/common/snippets/docs/debug_capabilities/linear_ir_passes_serialization.md b/src/common/snippets/docs/debug_capabilities/linear_ir_passes_serialization.md index 8fc016876ec0c4..2d9e4cbf56a63e 100644 --- a/src/common/snippets/docs/debug_capabilities/linear_ir_passes_serialization.md +++ b/src/common/snippets/docs/debug_capabilities/linear_ir_passes_serialization.md @@ -16,15 +16,26 @@ Examples: OV_SNIPPETS_DUMP_LIR="passes=ExtractLoopInvariants dir=path/dumpdir formats=all" binary ... OV_SNIPPETS_DUMP_LIR="passes=all dir=path/dumpdir formats=control_flow" binary ... OV_SNIPPETS_DUMP_LIR="passes=FuseLoops,InsertLoops,InsertLoadStore formats=data_flow" binary ... + OV_SNIPPETS_DUMP_LIR="passes=final formats=control_flow name_modifier=subgraph_name" binary ... + OV_SNIPPETS_DUMP_LIR="passes=all dir=path/dumpdir name_modifier=branchA" binary ... ``` +Dumped files have below names: + - Regular passes: `lir___(control_flow|data_flow)_(in|out).xml` (creates both input and output files) + - Final dump: `lir__Final_(control_flow|data_flow).xml` (creates single file only) + +When `name_modifier` is provided, it is prepended to file names as a prefix: + - `name_modifier=subgraph_name` prepends the Snippets Subgraph friendly name where available (e.g., final dump). + - any other non-empty value prepends that literal value (e.g., `branchA_lir_...`). + Option names are case insensitive, the following options are supported: - `passes` : Dump LIR around the passes if passes name are specified. It support multiple comma separated pass names. The names are case insensitive. - Key word 'all' means to dump LIR around every pass. This option is a must have, should not be omitted. + Special values: 'all' - dump all passes (includes 'final'), 'final' - dump final LIR snapshot right before code generation (single file, no _in/_out suffix). - `dir` : Path to dumped LIR files. If omitted, it defaults to snippets_LIR_dump. If specified path doesn't exist, the directory will be created automatically. - `formats` : Support values are control_flow, data_flow and all. - If omitted, it defaults to control_flow. \ No newline at end of file + If omitted, it defaults to control_flow. + - `name_modifier` : Optional file-name prefix. Special value `subgraph_name` prepends the Snippets Subgraph friendly name to dumped files (where available). Any other non-empty value is used as a literal prefix. If omitted, no name modification is performed. Note: when using `subgraph_name`, characters '/' and ':' in the subgraph name are replaced with '_' for filesystem compatibility. diff --git a/src/common/snippets/include/snippets/lowered/linear_ir.hpp b/src/common/snippets/include/snippets/lowered/linear_ir.hpp index 98086386d708f1..775b1f8e7fd3fd 100644 --- a/src/common/snippets/include/snippets/lowered/linear_ir.hpp +++ b/src/common/snippets/include/snippets/lowered/linear_ir.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -102,7 +103,12 @@ class LinearIR { size_t get_static_buffer_scratchpad_size() const { return m_static_buffer_scratchpad_size; } - + const std::string& get_friendly_name() const { + return m_friendly_name; + } + void set_friendly_name(std::string name) { + m_friendly_name = std::move(name); + } void set_loop_depth(size_t loop_depth) { m_config.m_loop_depth = loop_depth; } @@ -394,6 +400,8 @@ class LinearIR { // Size of static Buffer Scratchpad (Buffers with defined allocation size) size_t m_static_buffer_scratchpad_size = 0; + // Human-readable identifier; typically set from Subgraph node friendly name + std::string m_friendly_name; }; using LinearIRPtr = std::shared_ptr; using LinearIRCPtr = std::shared_ptr; diff --git a/src/common/snippets/include/snippets/utils/debug_caps_config.hpp b/src/common/snippets/include/snippets/utils/debug_caps_config.hpp index 74e91b4785b83a..af35e391d8cbae 100644 --- a/src/common/snippets/include/snippets/utils/debug_caps_config.hpp +++ b/src/common/snippets/include/snippets/utils/debug_caps_config.hpp @@ -51,6 +51,7 @@ class DebugCapsConfig { std::string dir = "snippets_LIR_dump"; LIRFormatFilter format = {1 << LIRFormatFilter::controlFlow}; std::vector passes; + std::string name_modifier; std::vector getPropertySetters() override { return {PropertySetterPtr(new StringPropertySetter("dir", dir, "path to dumped LIRs")), @@ -59,7 +60,13 @@ class DebugCapsConfig { "passes", passes, "indicate dump LIRs around the passes. Support multiple passes with comma separated and case " - "insensitive. 'all' means dump all passes"))}; + "insensitive. Special values: 'all' - dump all passes (includes 'final'), 'final' - dump final " + "LIR")), + PropertySetterPtr(new StringPropertySetter( + "name_modifier", + name_modifier, + "optional file-name prefix; special value 'subgraph_name' uses the Subgraph friendly name; any " + "other non-empty value is used as a literal prefix"))}; } } dumpLIR; diff --git a/src/common/snippets/include/snippets/utils/linear_ir_pass_dumper.hpp b/src/common/snippets/include/snippets/utils/linear_ir_pass_dumper.hpp index b36cd47ef80e56..8c32fb29a48130 100644 --- a/src/common/snippets/include/snippets/utils/linear_ir_pass_dumper.hpp +++ b/src/common/snippets/include/snippets/utils/linear_ir_pass_dumper.hpp @@ -7,6 +7,7 @@ #include #ifdef SNIPPETS_DEBUG_CAPS +# include "openvino/util/common_util.hpp" # include "openvino/util/file_util.hpp" # include "snippets/lowered/linear_ir.hpp" # include "snippets/lowered/pass/serialize_control_flow.hpp" @@ -17,20 +18,41 @@ namespace ov::snippets { class LIRPassDump { public: - explicit LIRPassDump(const lowered::LinearIR& linear_ir, std::string pass_name) + enum class DumpMode : uint8_t { Both, SingleDump }; + + explicit LIRPassDump(const lowered::LinearIR& linear_ir, std::string pass_name, DumpMode mode = DumpMode::Both) : linear_ir(linear_ir), pass_name(std::move(pass_name)), + dump_mode(mode), debug_config(*linear_ir.get_config().debug_config) { - dump("_in"); + if (dump_mode == DumpMode::Both) { + dump("_in"); + } else { + dump(""); + } } ~LIRPassDump() { - dump("_out"); + if (dump_mode == DumpMode::Both) { + dump("_out"); + } } private: void dump(const std::string&& postfix) const { static int num = 0; // just to keep dumped IRs ordered in filesystem - const auto pathAndName = debug_config.dumpLIR.dir + "/lir_"; + auto pathAndName = debug_config.dumpLIR.dir + "/"; + const auto nm_lower = ov::util::to_lower(debug_config.dumpLIR.name_modifier); + if (nm_lower == std::string("subgraph_name")) { + auto name_prefix = linear_ir.get_friendly_name(); + // Replace '/' and ':' characters with '_' to ensure filesystem compatibility + // These characters are problematic in file paths + std::replace(name_prefix.begin(), name_prefix.end(), '/', '_'); + std::replace(name_prefix.begin(), name_prefix.end(), ':', '_'); + pathAndName += name_prefix + "_"; + } else if (!debug_config.dumpLIR.name_modifier.empty()) { + pathAndName += debug_config.dumpLIR.name_modifier + "_"; + } + pathAndName += "lir_"; ov::util::create_directory_recursive(debug_config.dumpLIR.dir); @@ -51,6 +73,7 @@ class LIRPassDump { const lowered::LinearIR& linear_ir; const std::string pass_name; + const DumpMode dump_mode; const DebugCapsConfig& debug_config; }; @@ -67,4 +90,4 @@ class LIRPassDump { : nullptr #else # define SNIPPETS_DEBUG_LIR_PASS_DUMP(_linear_ir, _pass) -#endif // SNIPPETS_DEBUG_CAPS \ No newline at end of file +#endif // SNIPPETS_DEBUG_CAPS diff --git a/src/common/snippets/src/lowered/linear_ir_builder.cpp b/src/common/snippets/src/lowered/linear_ir_builder.cpp index ac460f79856d18..7744c26c360a8c 100644 --- a/src/common/snippets/src/lowered/linear_ir_builder.cpp +++ b/src/common/snippets/src/lowered/linear_ir_builder.cpp @@ -80,6 +80,7 @@ std::vector> clone_nodes(const std::vectorm_config = src->m_config; + dst->m_friendly_name = src->m_friendly_name; dst->m_expressions = clone_range(src->m_expressions.cbegin(), src->m_expressions.cend(), expression_map); for (const auto& expr : dst->m_expressions) { diff --git a/src/common/snippets/src/op/subgraph.cpp b/src/common/snippets/src/op/subgraph.cpp index 385cc08f4e7a93..6d5e6d89f3c1ad 100644 --- a/src/common/snippets/src/op/subgraph.cpp +++ b/src/common/snippets/src/op/subgraph.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,7 @@ #include "snippets/shape_inference/shape_inference.hpp" #include "snippets/shape_types.hpp" #include "snippets/utils/debug_caps_config.hpp" +#include "snippets/utils/linear_ir_pass_dumper.hpp" #include "snippets/utils/utils.hpp" using namespace ov::op::util; @@ -412,6 +414,7 @@ std::shared_ptr Subgraph::convert_body_to_linear_ir( #endif // SNIPPETS_DEBUG_CAPS m_linear_ir = std::make_shared(body_ptr(), shape_infer_factory, lowering_config); + m_linear_ir->set_friendly_name(get_friendly_name()); m_shape_infer = m_linear_ir->get_shape_infer_instance(); return m_linear_ir; } @@ -619,6 +622,17 @@ snippets::Schedule Subgraph::generate(const void* compile_params) const { shape_dependent_pipeline.run(*linear_ir); } +#ifdef SNIPPETS_DEBUG_CAPS + const auto& debug_conf = *linear_ir->get_config().debug_config; + const auto& dump_names = debug_conf.dumpLIR.passes; + const bool dump_final = + (std::find(dump_names.begin(), dump_names.end(), std::string("final")) != dump_names.end()) || + (std::find(dump_names.begin(), dump_names.end(), std::string("all")) != dump_names.end()); + if (dump_final) { + LIRPassDump final_dump(*linear_ir, std::string("Final"), LIRPassDump::DumpMode::SingleDump); + } +#endif + auto lowering_result = m_generator->generate(linear_ir, compile_params); return Schedule{std::move(lowering_result)}; }