• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019-2023 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "include/common/debug/anf_ir_dump.h"
17 #if defined(_WIN32) || defined(_WIN64)
18 #include <stdlib.h>
19 #endif
20 #include <fstream>
21 #include <iomanip>
22 #include <nlohmann/json.hpp>
23 #include "mindspore/core/ops/structure_ops.h"
24 #include "utils/label.h"
25 #include "utils/hash_map.h"
26 #include "utils/hash_set.h"
27 #include "utils/symbolic.h"
28 #include "utils/compile_config.h"
29 #include "ir/primitive.h"
30 #include "ir/func_graph.h"
31 #include "ir/graph_utils.h"
32 #include "ir/value.h"
33 #include "utils/trace_base.h"
34 #include "utils/anf_utils.h"
35 #include "include/common/utils/anfalgo.h"
36 #include "include/common/debug/anf_dump_utils.h"
37 #include "mindspore/core/utils/file_utils.h"
38 #include "ir/meta_func_graph.h"
39 #include "pipeline/jit/ps/parse/resolve.h"
40 #include "frontend/operator/composite/composite.h"
41 #include "frontend/expander/bprop/bprop_meta_func_graph.h"
42 #include "frontend/operator/composite/vmap.h"
43 #include "frontend/operator/composite/map.h"
44 
45 using MetaFuncGraph = mindspore::MetaFuncGraph;
46 using MetaFuncGraphPtr = std::shared_ptr<MetaFuncGraph>;
47 namespace mindspore {
48 
49 enum FormatLevel : int {
50   // When setting to basic level, ir will only contains operator and operands of nodes and title of subgraph with
51   // its debuginfo
52   kBasicLevel = 0,
53   // When setting to advanced level, ir will contains all the info except scope and debug info of nodes.
54   kAdvancedLevel,
55   // When setting to advanced level, ir will contains all the info.
56   kFullyLevel,
57 };
58 
GetMultitypeFuncGraphText(const prim::MultitypeFuncGraphPtr & mt_func_graph)59 std::string GetMultitypeFuncGraphText(const prim::MultitypeFuncGraphPtr &mt_func_graph) {
60   auto py_funcs = mt_func_graph->GetPyFunctions();
61   if (py_funcs.empty()) {
62     return "";
63   }
64 
65   std::ostringstream oss;
66 
67   oss << "{";
68   bool is_first = true;
69   for (const auto &py_func : py_funcs) {
70     if (is_first) {
71       is_first = false;
72     } else {
73       oss << ", ";
74     }
75     oss << "(";
76     for (size_t i = 0; i < py_func.first.size(); ++i) {
77       if (i > 0) {
78         oss << ", ";
79       }
80       oss << py_func.first[i]->DumpText();
81     }
82     oss << ")";
83   }
84   oss << "}";
85 
86   return oss.str();
87 }
88 
Skip(const MetaFuncGraphPtr & meta_func_graph)89 inline bool Skip(const MetaFuncGraphPtr &meta_func_graph) {
90   return meta_func_graph->isa<prim::Tail>() || meta_func_graph->isa<prim::MakeTupleGradient>() ||
91          meta_func_graph->isa<prim::MakeListGradient>() || meta_func_graph->isa<prim::MakeDictGradient>() ||
92          meta_func_graph->isa<prim::TupleAdd>() || meta_func_graph->isa<prim::SequenceSliceGetItem>() ||
93          meta_func_graph->isa<prim::ListSliceSetItem>() || meta_func_graph->isa<prim::UnpackCall>() ||
94          meta_func_graph->isa<prim::ZipOperation>() || meta_func_graph->isa<prim::ListAppend>() ||
95          meta_func_graph->isa<prim::ListInsert>() || meta_func_graph->isa<prim::DoSignatureMetaFuncGraph>() ||
96          meta_func_graph->isa<prim::VmapMatchOutAxis>() || meta_func_graph->isa<prim::VmapGeneralPreprocess>() ||
97          meta_func_graph->isa<prim::GradAux>() || meta_func_graph->isa<prim::PyExecuteGradient>() ||
98          meta_func_graph->isa<prim::MutableGradient>() || meta_func_graph->isa<prim::ZerosLike>() ||
99          meta_func_graph->isa<prim::ListAdd>() || meta_func_graph->isa<prim::StarredGetItem>() ||
100          meta_func_graph->isa<prim::StarredUnpack>() || meta_func_graph->isa<prim::StarredUnpackMerge>() ||
101          meta_func_graph->isa<prim::IterConverter>() || meta_func_graph->isa<prim::HasNext>() ||
102          meta_func_graph->isa<prim::Next>();
103 }
104 
GetMetaFuncGraphText(const MetaFuncGraphPtr & meta_func_graph)105 std::string GetMetaFuncGraphText(const MetaFuncGraphPtr &meta_func_graph) {
106   if (meta_func_graph == nullptr) {
107     return "";
108   }
109 
110   std::ostringstream oss;
111   oss << meta_func_graph->type_name() << "_" << meta_func_graph->name();
112 
113   if (meta_func_graph->isa<prim::MultitypeFuncGraph>()) {
114     prim::MultitypeFuncGraphPtr mt_func_graph = meta_func_graph->cast<prim::MultitypeFuncGraphPtr>();
115     oss << GetMultitypeFuncGraphText(mt_func_graph);
116   } else if (meta_func_graph
117                ->isa<prim::HyperMapPy>()) {  // This statement must before 'meta_graph->isa<prim::HyperMap>()'
118     auto hyper_map = meta_func_graph->cast<prim::HyperMapPyPtr>();
119     if (hyper_map->GetFnLeaf() != nullptr) {
120       oss << "{fn_leaf: " << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
121     }
122   } else if (meta_func_graph->isa<prim::HyperMap>()) {
123     auto hyper_map = meta_func_graph->cast<prim::HyperMapPtr>();
124     if (hyper_map->GetFnLeaf() != nullptr) {
125       oss << "{fn_leaf: " << GetMetaFuncGraphText(hyper_map->GetFnLeaf()) << "}";
126     }
127   } else if (meta_func_graph->isa<prim::MapPy>()) {  // This statement must before 'meta_graph->isa<prim::Map>()'
128     auto map = meta_func_graph->cast<prim::MapPyPtr>();
129     if (map->GetFnLeaf() != nullptr) {
130       oss << "{fn_leaf: " << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
131     }
132   } else if (meta_func_graph->isa<prim::Map>()) {
133     auto map = meta_func_graph->cast<prim::MapPtr>();
134     if (map->GetFnLeaf() != nullptr) {
135       oss << "{fn_leaf: " << GetMetaFuncGraphText(map->GetFnLeaf()) << "}";
136     }
137   } else if (meta_func_graph->isa<prim::GradOperation>()) {
138     prim::GradOperationPtr grad_op = meta_func_graph->cast<prim::GradOperationPtr>();
139     oss << "{get_all: " << grad_op->get_all_ << ", get_by_list: " << grad_op->get_by_list_
140         << ", sens_param: " << grad_op->sens_param_ << "}";
141   } else if (meta_func_graph->isa<prim::VmapGeneralRule>()) {
142     prim::VmapGeneralRulePtr general_rule_fg = meta_func_graph->cast<prim::VmapGeneralRulePtr>();
143     oss << "{prim: " << general_rule_fg->prim_name() << ", axis_size: " << general_rule_fg->axis_size() << "}";
144   } else if (meta_func_graph->isa<expander::bprop::BpropMetaFuncGraph>()) {
145     oss << "{" << meta_func_graph->name() << "}";
146   } else if (Skip(meta_func_graph)) {
147     // Do nothing.
148   } else {
149     MS_LOG(INTERNAL_EXCEPTION) << "Unknown MetaFuncGraph type " << meta_func_graph->type_name();
150   }
151 
152   return oss.str();
153 }
154 
GetPrimitiveText(const PrimitivePtr & prim)155 std::string GetPrimitiveText(const PrimitivePtr &prim) {
156   std::ostringstream oss;
157   if (!prim->instance_name().empty()) {
158     oss << " {";
159     oss << "instance name"
160         << ": ";
161     oss << prim->instance_name();
162     oss << "}";
163   }
164   auto attrs = prim->attrs();
165   if (!attrs.empty()) {
166     oss << " primitive_attrs: {";
167     oss << prim->GetAttrsText();
168     oss << "}";
169   }
170 
171   if (prim->isa<prim::DoSignaturePrimitive>()) {
172     auto do_signature = dyn_cast<prim::DoSignaturePrimitive>(prim);
173     auto &func = do_signature->function();
174     if (func->isa<Primitive>()) {
175       auto sig_prim = dyn_cast<Primitive>(func);
176       oss << sig_prim->GetAttrsText();
177     }
178   }
179 
180   return oss.str();
181 }
182 
GetSequenceText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)183 std::string GetSequenceText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
184   std::ostringstream oss;
185   // Output ValueList, ValueTuple
186   ValueSequencePtr seq = dyn_cast<ValueSequence>(value);
187   MS_EXCEPTION_IF_NULL(seq);
188   MS_EXCEPTION_IF_NULL(value);
189   bool is_tuple = value->isa<ValueTuple>();
190   oss << (is_tuple ? "(" : "[");
191   bool first_flag = true;
192   for (auto elem : seq->value()) {
193     if (first_flag) {
194       first_flag = false;
195     } else {
196       oss << ", ";
197     }
198     oss << GetValueText(elem, gsub);
199   }
200   oss << (is_tuple ? ")" : "]");
201   return oss.str();
202 }
203 
GetDictText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)204 std::string GetDictText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
205   std::ostringstream oss;
206   MS_EXCEPTION_IF_NULL(value);
207   ValueDictionaryPtr dict = value->cast<ValueDictionaryPtr>();
208   oss << "{";
209   bool first_flag = true;
210   for (const auto &elem : dict->value()) {
211     if (first_flag) {
212       first_flag = false;
213     } else {
214       oss << ", ";
215     }
216     oss << "\"" << elem.first->ToString() << "\": " << GetValueText(elem.second, gsub);
217   }
218   oss << "}";
219   return oss.str();
220 }
221 
GetOtherValueText(const ValuePtr & value)222 std::string GetOtherValueText(const ValuePtr &value) {
223   std::ostringstream oss;
224   oss << value->type_name() << "[" << value->ToString() << "]";
225   return oss.str();
226 }
227 
CanUseDumpText(const ValuePtr & value)228 static bool CanUseDumpText(const ValuePtr &value) {
229   return (value->isa<RefKey>() || value->isa<Scalar>() || value->isa<StringImm>() || value->isa<tensor::Tensor>() ||
230           value->isa<parse::Symbol>() || value->isa<None>() || value->isa<Null>() || value->isa<ValueSlice>() ||
231           value->isa<Type>() || value->isa<KeywordArg>() || value->isa<SymbolicKeyInstance>());
232 }
233 
GetValueText(const ValuePtr & value,const std::shared_ptr<SubGraphIRInfo> & gsub)234 std::string GetValueText(const ValuePtr &value, const std::shared_ptr<SubGraphIRInfo> &gsub) {
235   MS_EXCEPTION_IF_NULL(value);
236   if (value->isa<Primitive>()) {
237     return GetPrimitiveText(value->cast<PrimitivePtr>());
238   }
239   if (value->isa<MetaFuncGraph>()) {
240     MetaFuncGraphPtr meta_func_graph = value->cast<MetaFuncGraphPtr>();
241     return GetMetaFuncGraphText(meta_func_graph);
242   }
243   if (value->isa<ValueSequence>()) {
244     return GetSequenceText(value, gsub);
245   }
246   if (value->isa<ValueDictionary>()) {
247     return GetDictText(value, gsub);
248   }
249   if (CanUseDumpText(value)) {
250     return value->DumpText();
251   } else {
252     return GetOtherValueText(value);
253   }
254 }
255 
PrintTupleNodeUsedFlags(std::ostringstream & buffer,const abstract::AbstractSequencePtr & sequence_abs)256 void PrintTupleNodeUsedFlags(std::ostringstream &buffer, const abstract::AbstractSequencePtr &sequence_abs) {
257   if (sequence_abs == nullptr || sequence_abs->sequence_nodes() == nullptr || sequence_abs->sequence_nodes()->empty()) {
258     return;
259   }
260   static const bool dump_dde_detail = (common::GetCompileConfig("DUMP_IR_DDE_DETAIL") == "1");
261   if (dump_dde_detail) {
262     buffer << ", sequence_nodes={";
263     for (size_t i = 0; i < sequence_abs->sequence_nodes()->size(); ++i) {
264       auto node = (*sequence_abs->sequence_nodes())[i].lock();
265       if (node == nullptr) {
266         MS_LOG(DEBUG) << "The node in sequence_nodes is free.";
267         buffer << "node={<freed node>}";
268       } else {
269         buffer << "node={" << node << "/" << node->DebugString();
270         auto flags = GetSequenceNodeElementsUseFlags(node);
271         if (flags != nullptr) {
272           buffer << ", elements_use_flags: {ptr: " << flags << ", value: " << (*flags) << "}";
273         }
274         buffer << "}";
275       }
276       if (i != sequence_abs->sequence_nodes()->size() - 1) {
277         buffer << ", ";
278       }
279     }
280     buffer << "}";
281   } else {
282     buffer << ", elements_use_flags={";
283     for (size_t i = 0; i < sequence_abs->sequence_nodes()->size(); ++i) {
284       auto node = (*sequence_abs->sequence_nodes())[i].lock();
285       if (node == nullptr) {
286         continue;
287       }
288       auto flags = GetSequenceNodeElementsUseFlags(node);
289       if (flags != nullptr) {
290         buffer << (*flags);
291         break;
292       }
293     }
294     buffer << "}";
295   }
296 }
297 
PrintNodeOutputType(std::ostringstream & buffer,const AnfNodePtr & node)298 void PrintNodeOutputType(std::ostringstream &buffer, const AnfNodePtr &node) {
299   if (node == nullptr) {
300     return;
301   }
302 
303   ValuePtr tensor_value = nullptr;
304   StringImmPtr ref_key = nullptr;
305   abstract::AbstractSequencePtr sequence_abs = nullptr;
306   auto abstract = node->abstract();
307   if (abstract != nullptr) {
308     if (abstract->isa<abstract::AbstractTensor>()) {
309       tensor_value = abstract->BuildValue();
310     }
311     if (auto ref_tensor = abstract->cast_ptr<abstract::AbstractRefTensor>(); ref_tensor != nullptr) {
312       ref_key = dyn_cast<StringImm>(ref_tensor->ref_key_value());
313     } else if (auto map_tensor = abstract->cast_ptr<abstract::AbstractMapTensor>(); map_tensor != nullptr) {
314       ref_key = dyn_cast<StringImm>(map_tensor->ref_key_value());
315     }
316     sequence_abs = dyn_cast<abstract::AbstractSequence>(abstract);
317   }
318 
319   abstract::BaseShapePtr shape = dyn_cast<abstract::BaseShape>(node->Shape());
320   TypePtr type = dyn_cast<Type>(node->Type());
321   if ((shape != nullptr) && (type != nullptr)) {
322     buffer << "<" << type << ", " << shape->ToString();
323     if (tensor_value != nullptr && tensor_value != kValueAny) {
324       buffer << ", value=...";
325     }
326     if (ref_key != nullptr) {
327       buffer << ", ref_key=" << ref_key->value();
328     }
329     PrintTupleNodeUsedFlags(buffer, sequence_abs);
330     buffer << ">";
331   } else if (type != nullptr) {
332     buffer << "<" << type;
333     if (tensor_value != nullptr && tensor_value != kValueAny) {
334       buffer << ", value=...";
335     }
336     if (ref_key != nullptr) {
337       buffer << ", ref_key=" << ref_key->value();
338     }
339     PrintTupleNodeUsedFlags(buffer, sequence_abs);
340     buffer << ">";
341   } else {
342     buffer << "<null>";
343   }
344 }
345 
PrintNodeInputType(std::ostringstream & buffer,const AnfNodePtr & node)346 void PrintNodeInputType(std::ostringstream &buffer, const AnfNodePtr &node) {
347   if (node == nullptr) {
348     return;
349   }
350 
351   const auto &inputs = GetInputs(node);
352   size_t len = inputs.size();
353   if (len > 1) {
354     // Skip inputs[0] which is Primitive value node
355     for (size_t i = 1; i < len; ++i) {
356       AnfNodePtr in = inputs[i];
357       if (i != 1) {
358         buffer << ", ";
359       }
360       PrintNodeOutputType(buffer, in);
361     }
362   }
363 }
364 
PrintNodeOutputSymbolicInfo(std::ostringstream & buffer,const AnfNodePtr & node)365 void PrintNodeOutputSymbolicInfo(std::ostringstream &buffer, const AnfNodePtr &node) {
366   if (node == nullptr) {
367     return;
368   }
369   auto abstract = node->abstract();
370   if (abstract == nullptr) {
371     buffer << "<null>";
372     return;
373   }
374   auto shape = abstract->GetSymbolicShape();
375   auto value = abstract->GetSymbolicValue();
376   if (shape != nullptr || value != nullptr) {
377     if (shape != nullptr) {
378       buffer << "S:" << shape->ToString();
379     }
380     if (value != nullptr) {
381       buffer << "V:" << value->ToString();
382     }
383   } else {
384     buffer << "<null>";
385   }
386 }
387 
PrintNodeInputSymbolicInfo(std::ostringstream & buffer,const AnfNodePtr & node)388 void PrintNodeInputSymbolicInfo(std::ostringstream &buffer, const AnfNodePtr &node) {
389   if (node == nullptr) {
390     return;
391   }
392   const auto &inputs = GetInputs(node);
393   if (inputs.size() <= 1) {
394     return;
395   }
396   for (size_t i = 1; i < inputs.size(); ++i) {
397     if (i != 1) {
398       buffer << ", ";
399     }
400     PrintNodeOutputSymbolicInfo(buffer, inputs[i]);
401   }
402 }
403 
DumpSymbolicInfo(const AnfNodePtr & node,const FuncGraphPtr & fg,const std::shared_ptr<SubGraphIRInfo> & gsub)404 void DumpSymbolicInfo(const AnfNodePtr &node, const FuncGraphPtr &fg, const std::shared_ptr<SubGraphIRInfo> &gsub) {
405   if (node == nullptr || fg == nullptr || gsub == nullptr || fg->symbol_engine() == nullptr) {
406     return;
407   }
408   if (node != fg->get_return()) {
409     gsub->buffer << "      : (";
410     PrintNodeInputSymbolicInfo(gsub->buffer, node);
411     gsub->buffer << ") -> (";
412     PrintNodeOutputSymbolicInfo(gsub->buffer, node);
413     gsub->buffer << ")";
414   } else {
415     gsub->buffer << "      : (";
416     PrintNodeInputSymbolicInfo(gsub->buffer, node);
417     gsub->buffer << ")";
418   }
419   gsub->buffer << std::endl;
420 }
421 
PrintParamSymbolicShape(std::ostringstream & buffer,const AnfNodePtr & node)422 void PrintParamSymbolicShape(std::ostringstream &buffer, const AnfNodePtr &node) {
423   if (node == nullptr) {
424     return;
425   }
426   auto abstract = node->abstract();
427   if (abstract == nullptr) {
428     return;
429   }
430   SymbolPtr shape = abstract->GetSymbolicShape();
431   if (shape != nullptr) {
432     buffer << " : " << shape->ToString();
433   }
434 }
435 
GatherInputAndOutputInferType(std::ostringstream & buffer,const AnfNodePtr & node)436 void GatherInputAndOutputInferType(std::ostringstream &buffer, const AnfNodePtr &node) {
437   buffer << "      : (";
438   PrintNodeInputType(buffer, node);
439   buffer << ") -> (";
440   PrintNodeOutputType(buffer, node);
441   buffer << ")";
442 }
443 
DumpGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer,size_t sub_graphs_size)444 void DumpGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer, size_t sub_graphs_size) {
445   if (graph == nullptr) {
446     return;
447   }
448 
449   buffer << "# IR entry: @" << graph->ToString() << std::endl;
450   buffer << "# Total subgraphs: " << sub_graphs_size << std::endl;
451   buffer << std::endl;
452 
453   if (!graph->attrs().empty()) {
454     buffer << "# Attrs:" << std::endl;
455     for (const auto &attr : graph->attrs()) {
456       buffer << attr.first << ": ";
457       if (attr.second->isa<BoolImm>()) {
458         buffer << GetValue<bool>(attr.second);
459       } else if (attr.second->isa<StringImm>()) {
460         buffer << GetValue<std::string>(attr.second);
461       }
462       buffer << std::endl;
463     }
464     buffer << std::endl;
465   }
466 }
467 
DumpKernelObjectType(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)468 void DumpKernelObjectType(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
469   auto inputs_str = AnfDumpHandler::PrintInputKernelObjectTypes(node);
470   auto outputs_str = AnfDumpHandler::PrintOutputKernelObjectTypes(node);
471   if (inputs_str.empty() && outputs_str.empty()) {
472     return;
473   }
474   gsub->buffer << "      : (" << inputs_str << ") -> (" << outputs_str << ")" << std::endl;
475 }
476 
DumpKernelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)477 void DumpKernelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
478   if (node == nullptr || gsub == nullptr) {
479     return;
480   }
481   auto kernel_info = node->kernel_info();
482   if (kernel_info == nullptr || !kernel_info->has_build_info()) {
483     return;
484   }
485   if (!AnfUtils::IsRealKernel(node)) {
486     DumpKernelObjectType(node, gsub);
487     return;
488   }
489 
490   gsub->buffer << "      : (";
491   gsub->buffer << AnfDumpHandler::PrintInputTypeShapeFormat(node);
492   gsub->buffer << ") -> (";
493   gsub->buffer << AnfDumpHandler::PrintOutputTypeShapeFormat(node);
494   gsub->buffer << ")";
495   gsub->buffer << std::endl;
496   DumpKernelObjectType(node, gsub);
497 }
498 
DumpParams(const FuncGraphPtr & graph,std::ostringstream & buffer,OrderedMap<AnfNodePtr,int32_t> * para_map)499 int32_t DumpParams(const FuncGraphPtr &graph, std::ostringstream &buffer, OrderedMap<AnfNodePtr, int32_t> *para_map) {
500   if (graph == nullptr) {
501     MS_LOG(INFO) << "Parameter \'graph\' should not be null.";
502     return 0;
503   }
504   std::vector<AnfNodePtr> parameters = graph->parameters();
505   buffer << "# Total params: " << parameters.size() << std::endl;
506 
507   if (parameters.empty()) {
508     return 0;
509   }
510   buffer << "# Params:" << std::endl;
511   // Dump parameters
512   int32_t para_num = 1;
513   for (const auto &param : parameters) {
514     if (param == nullptr) {
515       continue;
516     }
517     auto parameter_ptr = param->cast<ParameterPtr>();
518     if (parameter_ptr == nullptr) {
519       MS_LOG(INTERNAL_EXCEPTION) << "param cannot cast to ParameterPtr";
520     }
521     buffer << "%para" << para_num << "_" << parameter_ptr->name() << ": ";
522     // Print parameters' type and shape
523     PrintNodeOutputType(buffer, param);
524     PrintParamSymbolicShape(buffer, param);
525     if (parameter_ptr->has_default()) {
526       buffer << "  :  has_default";
527     }
528     auto kernel_info = param->kernel_info();
529     if (kernel_info != nullptr && kernel_info->has_build_info()) {
530       buffer << "  :  ";
531       buffer << AnfDumpHandler::PrintOutputTypeShapeFormat(param);
532       buffer << "  :  IsWeight: " << std::boolalpha << common::AnfAlgo::IsParameterWeight(parameter_ptr);
533     }
534     buffer << std::endl;
535 
536     if (para_map != nullptr) {
537       (*para_map)[param] = para_num++;
538     }
539     if (param->func_graph() == nullptr) {
540       MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << param->DebugString();
541     }
542     MS_LOG(DEBUG) << "Record param: " << param->ToString() << " graph belong : " << param->func_graph()->ToString();
543   }
544   return para_num;
545 }
546 
DumpParameterOperator(const AnfNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub,const AnfNodePtr & op)547 void DumpParameterOperator(const AnfNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub, const AnfNodePtr &op) {
548   if (op->func_graph() != nullptr && op->func_graph() != node->func_graph()) {
549     gsub->buffer << "$(@" << op->func_graph()->ToString() << ":";
550   }
551   gsub->buffer << op->ToString();
552   if (op->func_graph() != nullptr && op->func_graph() != node->func_graph()) {
553     gsub->buffer << ")";
554   }
555   std::string func_str = GetNodeFuncStr(op);
556   if (!func_str.empty()) {
557     gsub->buffer << "[@" << func_str << "]";
558   }
559 }
560 
DumpOperator(const AnfNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)561 void DumpOperator(const AnfNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
562   if (gsub == nullptr) {
563     MS_LOG(INFO) << "Parameter \'gsub\' should not be null.";
564     return;
565   }
566   auto cnode = dyn_cast<CNode>(node);
567   if (cnode == nullptr) {
568     MS_LOG(INTERNAL_EXCEPTION) << "Parameter \'node\' should be a CNode";
569   }
570   AnfNodePtr op = cnode->input(0);
571   MS_EXCEPTION_IF_NULL(op);
572   if (IsValueNode<FuncGraph>(op)) {
573     FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(op);
574     if (fg != nullptr) {
575       gsub->buffer << "call @" << fg->ToString();
576     }
577   } else if (op->isa<CNode>()) {
578     std::string func_str = GetNodeFuncStr(op);
579     if (gsub->local_var_map.find(op) != gsub->local_var_map.end()) {
580       gsub->buffer << "%" << gsub->local_var_map[op];
581     } else {
582       auto input = op->cast<CNodePtr>();
583       auto fg = input->func_graph();
584       if (fg == nullptr) {
585         MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << node->DebugString();
586       }
587       gsub->buffer << "$(@" << fg->ToString() << ":" << input->ToString() << ")";
588     }
589     if (!func_str.empty()) {
590       gsub->buffer << "[@" << func_str << "]";
591     }
592   } else if (op->isa<ValueNode>()) {
593     auto value = GetValueNode(op);
594     if (value != nullptr) {
595       if (value->isa<Primitive>()) {
596         gsub->buffer << value->ToString();
597       } else {
598         gsub->buffer << GetValueText(value, gsub);
599       }
600     }
601   } else {
602     // It's Parameter.
603     DumpParameterOperator(node, gsub, op);
604   }
605 }
606 
DumpParamterInOperand(const AnfNodePtr & node,const AnfNodePtr & in,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)607 void DumpParamterInOperand(const AnfNodePtr &node, const AnfNodePtr &in,
608                            const OrderedMap<AnfNodePtr, int32_t> &para_map,
609                            const std::shared_ptr<SubGraphIRInfo> &gsub) {
610   MS_EXCEPTION_IF_NULL(node);
611   MS_EXCEPTION_IF_NULL(node->func_graph());
612   MS_EXCEPTION_IF_NULL(in);
613   MS_EXCEPTION_IF_NULL(gsub);
614   if (in->func_graph() == nullptr) {
615     MS_LOG(INFO) << "Parameter should belong to a func graph. Check func graph: " << node->func_graph();
616   }
617   if (in->func_graph() != nullptr && in->func_graph() != node->func_graph()) {
618     gsub->buffer << "$(@" << in->func_graph()->ToString() << ":";
619   } else {
620     gsub->buffer << "%";
621   }
622   auto iter = para_map.find(in);
623   if (iter == para_map.end()) {
624     gsub->buffer << "para_" << in->ToString();
625   } else {
626     gsub->buffer << "para" << iter->second << "_" << in->ToString();
627   }
628   if (in->func_graph() != nullptr && in->func_graph() != node->func_graph()) {
629     gsub->buffer << ")";
630   }
631 }
632 
DumpOperands(const AnfNodePtr & node,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)633 void DumpOperands(const AnfNodePtr &node, const OrderedMap<AnfNodePtr, int32_t> &para_map,
634                   const std::shared_ptr<SubGraphIRInfo> &gsub) {
635   if (node == nullptr || gsub == nullptr) {
636     return;
637   }
638 
639   gsub->buffer << "(";
640   const auto &inputs = GetInputs(node);
641   size_t len = inputs.size();
642   if (len > 1) {
643     // Skip inputs[0] which is Primitive valuenode
644     for (size_t i = 1; i < len; ++i) {
645       AnfNodePtr in = inputs[i];
646       MS_EXCEPTION_IF_NULL(in);
647       if (i != 1) {
648         gsub->buffer << ", ";
649       }
650       if (in->isa<Parameter>()) {
651         DumpParamterInOperand(node, in, para_map, gsub);
652       } else if (in->isa<CNode>()) {
653         auto iter = gsub->local_var_map.find(in);
654         if (iter != gsub->local_var_map.end()) {
655           gsub->buffer << "%" << iter->second;
656         } else {
657           auto input = in->cast<CNodePtr>();
658           auto fg = input->func_graph();
659           if (fg == nullptr) {
660             MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << input->DebugString();
661           }
662           gsub->buffer << "$(@" << fg->ToString() << ":" << input->ToString() << ")";
663         }
664       } else if (in->isa<ValueNode>() && !IsValueNode<FuncGraph>(in)) {
665         // ValueNode except FuncGraph.
666         gsub->buffer << GetValueText(GetValueNode(in), gsub);
667       } else if (IsValueNode<FuncGraph>(in)) {
668         FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(in);
669         if (fg == nullptr) {
670           MS_LOG(EXCEPTION) << "Get func graph nullptr, node " << in->DebugString();
671         }
672         gsub->buffer << "@" << fg->ToString();
673       } else if (AnfUtils::IsCustomActorNode(in)) {
674         gsub->buffer << "%" << AnfUtils::GetCustomActorName(in);
675       } else {
676         gsub->buffer << in->ToString();
677       }
678     }
679   }
680   gsub->buffer << ")";
681 }
682 
DumpParallelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)683 void DumpParallelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
684   if ((node == nullptr) || (gsub == nullptr)) {
685     return;
686   }
687 
688   ValuePtr in_tmp = AnfDumpHandler::InStrategyValue(node);
689   if (in_tmp == nullptr) {
690     return;
691   }
692   gsub->buffer << " {in_strategy: ";
693   gsub->buffer << in_tmp->ToString();
694 
695   ValuePtr out_tmp = AnfDumpHandler::OutStrategyValue(node);
696   if (out_tmp != nullptr) {
697     gsub->buffer << ", out_strategy: ";
698     gsub->buffer << out_tmp->ToString();
699   }
700 
701   gsub->buffer << "}";
702 }
703 
DumpAttrs(const mindspore::HashMap<std::string,ValuePtr> & attrs,const std::shared_ptr<SubGraphIRInfo> & gsub,bool check_strategy=false)704 void DumpAttrs(const mindspore::HashMap<std::string, ValuePtr> &attrs, const std::shared_ptr<SubGraphIRInfo> &gsub,
705                bool check_strategy = false) {
706   int i = 0;
707   for (const auto &attr : attrs) {
708     if (check_strategy && attr.first == PARALLEL_STRATEGY) {
709       continue;  // Skip the strategy
710     }
711     if (i++ != 0) {
712       gsub->buffer << ", ";
713     }
714     gsub->buffer << attr.first << ": ";
715     if (attr.second == nullptr) {
716       gsub->buffer << "null";
717     } else {
718       if (CanUseDumpText(attr.second)) {
719         gsub->buffer << attr.second->DumpText();
720       } else {
721         gsub->buffer << attr.second->ToString();
722       }
723     }
724   }
725 }
726 
DumpOperateAttrs(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)727 void DumpOperateAttrs(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
728   if (op == nullptr || gsub == nullptr) {
729     return;
730   }
731 
732   if (IsValueNode<Primitive>(op)) {
733     PrimitivePtr primitive = GetValueNode<PrimitivePtr>(op);
734     if (!primitive->instance_name().empty()) {
735       gsub->buffer << " {";
736       gsub->buffer << "instance name"
737                    << ": ";
738       gsub->buffer << primitive->instance_name();
739       gsub->buffer << "}";
740     }
741     auto attrs = primitive->attrs();
742     if (!attrs.empty()) {
743       gsub->buffer << " primitive_attrs: {";
744       DumpAttrs(attrs, gsub, true);
745       gsub->buffer << "}";
746     }
747   }
748 }
749 
DumpCNodeAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)750 void DumpCNodeAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
751   if (op == nullptr || gsub == nullptr) {
752     return;
753   }
754   if (op->attrs().empty()) {
755     return;
756   }
757 
758   auto attrs = op->attrs();
759   gsub->buffer << " cnode_attrs: {";
760   DumpAttrs(attrs, gsub);
761   gsub->buffer << "}";
762 }
763 
DumpCNodePrimalAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)764 void DumpCNodePrimalAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
765   if (op == nullptr || gsub == nullptr) {
766     return;
767   }
768   if (op->primal_attrs().empty()) {
769     return;
770   }
771   auto primal_attrs = op->primal_attrs();
772   gsub->buffer << " cnode_primal_attrs: {";
773   DumpAttrs(primal_attrs, gsub);
774   gsub->buffer << "}";
775 }
776 
DumpShape(const AnfNodePtr & node,const FuncGraphPtr & sub_graph,const std::shared_ptr<SubGraphIRInfo> & gsub)777 void DumpShape(const AnfNodePtr &node, const FuncGraphPtr &sub_graph, const std::shared_ptr<SubGraphIRInfo> &gsub) {
778   if (node == nullptr || sub_graph == nullptr || gsub == nullptr) {
779     return;
780   }
781 
782   gsub->buffer << std::endl;
783   if (node != sub_graph->get_return()) {
784     gsub->buffer << "      : (";
785     PrintNodeInputType(gsub->buffer, node);
786     gsub->buffer << ") -> (";
787     PrintNodeOutputType(gsub->buffer, node);
788     gsub->buffer << ")";
789   } else {
790     gsub->buffer << "      : (";
791     PrintNodeInputType(gsub->buffer, node);
792     gsub->buffer << ")";
793   }
794 
795   gsub->buffer << std::endl;
796 }
797 
DumpLocationInCurrentScope(const DebugInfoPtr & debug_info,const std::shared_ptr<SubGraphIRInfo> & gsub)798 void DumpLocationInCurrentScope(const DebugInfoPtr &debug_info, const std::shared_ptr<SubGraphIRInfo> &gsub) {
799   auto dump_debug_info = debug_info;
800   std::list<DebugInfoPtr> need_dump_debug_infos;
801   const auto &shadow_debug_infos_map = debug_info->shadow_debug_infos_map();
802   HashSet<DebugInfoPtr> all_shadowed_debug_infos;
803   while (dump_debug_info != nullptr) {
804     need_dump_debug_infos.push_front(dump_debug_info);
805     auto iter = shadow_debug_infos_map.find(dump_debug_info);
806     if (iter != shadow_debug_infos_map.end()) {
807       DebugInfoPtr shadowed_debug_info = iter->first;
808       DebugInfoPtr shadow_debug_info = iter->second;
809       MS_LOG(DEBUG) << "Insert debug info, shadow_debug_info: " << shadow_debug_info << "/" << shadow_debug_info->name()
810                     << "/" << shadow_debug_info->debug_name() << "/"
811                     << trace::GetDebugInfoStr(shadow_debug_info, "", kSourceLineTipNextLine, true) << ", shadow_trace: "
812                     << (shadow_debug_info->trace_info() != nullptr ? shadow_debug_info->trace_info()->name() : "none")
813                     << ", shadowed_debug_info: " << shadowed_debug_info << "/" << shadowed_debug_info->name() << "/"
814                     << shadowed_debug_info->debug_name() << "/"
815                     << trace::GetDebugInfoStr(shadowed_debug_info, "", kSourceLineTipNextLine, true)
816                     << ", shadowed_trace: "
817                     << (shadowed_debug_info->trace_info() != nullptr ? shadowed_debug_info->trace_info()->name()
818                                                                      : "none");
819       need_dump_debug_infos.push_front(shadow_debug_info);
820       all_shadowed_debug_infos.emplace(shadowed_debug_info);
821     }
822     if (dump_debug_info->trace_info() == nullptr) {
823       break;
824     }
825     dump_debug_info = dump_debug_info->trace_info()->debug_info();
826   }
827   HashSet<std::string> visited_locations;
828   for (const auto &cur_debug_info : need_dump_debug_infos) {
829     if (cur_debug_info->location() != nullptr) {
830       auto debug_info_str = trace::GetDebugInfoStr(cur_debug_info, "", kSourceLineTipDiscard);
831       if (visited_locations.find(debug_info_str) == visited_locations.cend()) {
832         constexpr auto prefix = "      # ";
833         gsub->buffer << prefix << debug_info_str;
834         if (all_shadowed_debug_infos.count(cur_debug_info) != 0) {
835           constexpr auto shared_code_line_hint =
836             "<~~This line of code can be shared by multiple nodes, and may be duplicated./";
837           gsub->buffer << shared_code_line_hint;
838         }
839         gsub->buffer << "\n";
840         (void)visited_locations.insert(debug_info_str);
841       }
842     }
843   }
844 }
845 
DumpPrimalDebugInfos(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)846 void DumpPrimalDebugInfos(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
847   MS_EXCEPTION_IF_NULL(node);
848   auto primal_debug_infos = node->primal_debug_infos();
849   if (!primal_debug_infos.empty()) {
850     for (const auto &primal_debug_info : primal_debug_infos) {
851       std::string lines;
852       auto debug_info_str = trace::GetDebugInfoStr(primal_debug_info, "      # ", kSourceLineTipDiscard);
853       if (!debug_info_str.empty()) {
854         lines += debug_info_str + "\n";
855       }
856       gsub->buffer << "      # Corresponding forward node candidate:\n";
857       if (!lines.empty()) {
858         gsub->buffer << lines;
859       }
860     }
861   }
862 }
863 
DumpDebugInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub,const LocDumpMode & dump_location)864 void DumpDebugInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub,
865                    const LocDumpMode &dump_location) {
866   MS_EXCEPTION_IF_NULL(node);
867   // Dump comments firstly.
868   if (node->debug_info() != nullptr) {
869     const auto &debug_info = trace::GetSourceCodeDebugInfo(node->debug_info());
870     if (debug_info->location() != nullptr) {
871       const auto &comments = debug_info->location()->comments();
872       if (!comments.empty()) {
873         gsub->buffer << "      # Comment:\n";
874         for (auto &comment : comments) {
875           gsub->buffer << "        " << comment << '\n';
876         }
877       }
878     }
879   }
880 
881   // Dump line info.
882   if (dump_location == kTopStack) {
883     auto fused_debug_infos = node->fused_debug_infos();
884     if (!fused_debug_infos.empty()) {
885       for (const auto &debug_info : fused_debug_infos) {
886         std::string lines;
887         gsub->buffer << "      # Corresponding code candidate:\n";
888         auto debug_info_str = trace::GetDebugInfoStr(debug_info, "      # ", kSourceLineTipDiscard);
889         if (!debug_info_str.empty()) {
890           lines += debug_info_str + "\n";
891         }
892         if (!lines.empty()) {
893           gsub->buffer << lines;
894         }
895       }
896     } else {
897       auto debug_info_str = trace::GetDebugInfoStr(node->debug_info(), "      # ", kSourceLineTipDiscard);
898       if (!debug_info_str.empty()) {
899         gsub->buffer << debug_info_str << "\n";
900       }
901     }
902     DumpPrimalDebugInfos(node, gsub);
903   } else if (dump_location == kWholeStack) {
904     auto fused_debug_infos = node->fused_debug_infos();
905     if (!fused_debug_infos.empty()) {
906       for (const auto &debug_info : fused_debug_infos) {
907         gsub->buffer << "      # Corresponding code candidate:\n";
908         DumpLocationInCurrentScope(debug_info, gsub);
909       }
910     } else {
911       DumpLocationInCurrentScope(node->debug_info(), gsub);
912     }
913     // Print whole stack primal infos
914     auto primal_debug_infos = node->primal_debug_infos();
915     if (!primal_debug_infos.empty()) {
916       for (const auto &primal_debug_info : primal_debug_infos) {
917         gsub->buffer << "      # Corresponding forward node candidate:\n";
918         DumpLocationInCurrentScope(primal_debug_info, gsub);
919       }
920     }
921   }
922 
923   // Dump side effect info.
924   auto effect_info = node->GetEffectInfo();
925   if (effect_info.HasEffect()) {
926     gsub->buffer << "      # " << effect_info.ToString() << '\n';
927   }
928 }
929 
DumpParameters(const FuncGraphPtr & func_graph,std::ostringstream & oss)930 void DumpParameters(const FuncGraphPtr &func_graph, std::ostringstream &oss) {
931   std::vector<AnfNodePtr> parameters = func_graph->parameters();
932   oss << "# Parameters: " << parameters.size() << ", (";
933   if (parameters.size() == 1) {
934     MS_EXCEPTION_IF_NULL(parameters[0]);
935     PrintNodeOutputType(oss, parameters[0]);
936   } else if (parameters.size() > 1) {
937     for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
938       MS_EXCEPTION_IF_NULL(parameters[idx]);
939       PrintNodeOutputType(oss, parameters[idx]);
940       oss << ", ";
941     }
942     MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
943     PrintNodeOutputType(oss, parameters[parameters.size() - 1]);
944   }
945   oss << ")\n";
946 }
947 
DumpCNode(const CNodePtr & node,const FuncGraphPtr & sub_graph,const OrderedMap<AnfNodePtr,int32_t> & para_map,const std::shared_ptr<SubGraphIRInfo> & gsub,bool dump_full_name,LocDumpMode dump_location)948 void DumpCNode(const CNodePtr &node, const FuncGraphPtr &sub_graph, const OrderedMap<AnfNodePtr, int32_t> &para_map,
949                const std::shared_ptr<SubGraphIRInfo> &gsub, bool dump_full_name, LocDumpMode dump_location) {
950   if (node == nullptr || sub_graph == nullptr || gsub == nullptr) {
951     return;
952   }
953 
954   // Print for TopoSort circle indicator only.
955   if (node->has_user_data(kTopoSortCircle)) {
956     auto num = node->user_data<size_t>(kTopoSortCircle);
957     MS_EXCEPTION_IF_NULL(num);
958     gsub->buffer << "\n#------------------------> " << (*num) << "\n";
959   }
960 
961   // Print node's name.
962   if (node != sub_graph->get_return()) {
963     gsub->buffer << "  %" << gsub->local_var << "(" << node->ToString() << ")"
964                  << " = ";
965     gsub->local_var_map[node] = gsub->local_var++;
966   } else {
967     gsub->buffer << "  ";
968   }
969 
970   if (node->weak_inputs().empty()) {
971     MS_LOG(INTERNAL_EXCEPTION) << "Input of CNode is empty";
972   }
973 
974   // Print operator
975   DumpOperator(node, gsub);
976 
977   // Print operands
978   DumpOperands(node, para_map, gsub);
979 
980   if (gsub->format_level > kBasicLevel) {
981     // Print operator attrs
982     AnfNodePtr op = node->input(0);
983     DumpOperateAttrs(op, gsub);
984 
985     // Print cnode attrs
986     DumpCNodeAttrs(node, gsub);
987 
988     // Print cnode primal attrs
989     DumpCNodePrimalAttrs(node, gsub);
990 
991     // Print parallel info
992     DumpParallelInfo(node, gsub);
993   }
994 
995   if (gsub->format_level > kBasicLevel || node == sub_graph->get_return()) {
996     // Print shape info
997     DumpShape(node, sub_graph, gsub);
998 
999     // Print symbolic shape or symbolic value
1000     DumpSymbolicInfo(node, sub_graph, gsub);
1001 
1002     // Print kernel info
1003     DumpKernelInfo(node, gsub);
1004   } else {
1005     gsub->buffer << std::endl;
1006   }
1007 
1008   // Use environment variables to control extra info.
1009   if (gsub->format_level > kAdvancedLevel) {
1010     if (dump_full_name) {
1011       gsub->buffer << "      # Fullname with scope: (" << node->fullname_with_scope() << ")" << std::endl;
1012     } else {
1013       gsub->buffer << "      # Scope: (" << node->scope()->name() << ")" << std::endl;
1014     }
1015     // Print debug info
1016     DumpDebugInfo(node, gsub, dump_location);
1017   }
1018 }
1019 
OutputOrderList(const FuncGraphPtr & sub_graph,std::ostringstream & oss)1020 void OutputOrderList(const FuncGraphPtr &sub_graph, std::ostringstream &oss) {
1021   auto &order_list = sub_graph->order_list();
1022   if (order_list.empty()) {
1023     return;
1024   }
1025   constexpr int width = 4;
1026   oss << "# Order:\n";
1027   int i = 1;
1028   for (auto &weak_node : order_list) {
1029     const auto &node = weak_node.lock();
1030     if (node != nullptr) {
1031       oss << '#' << std::setw(width) << i << ": " << node->DebugString() << '\n';
1032     }
1033     ++i;
1034   }
1035 }
1036 
DumpSymbolEngine(const FuncGraphPtr & sub_graph,std::ostringstream & oss,int format_level)1037 void DumpSymbolEngine(const FuncGraphPtr &sub_graph, std::ostringstream &oss, int format_level) {
1038   if (format_level <= kAdvancedLevel) {
1039     return;
1040   }
1041   if (sub_graph->symbol_engine() != nullptr && sub_graph->symbol_engine()->func_graph() == sub_graph) {
1042     oss << "\nsymbol engine details:\n";
1043     oss << sub_graph->symbol_engine()->DumpText();
1044   }
1045 }
1046 
GetDumpFormatLevel()1047 int GetDumpFormatLevel() {
1048   static std::string format = common::GetEnv("MS_DEV_DUMP_IR_FORMAT");
1049   int format_level = 2;
1050   if (format.size() == 1) {
1051     try {
1052       format_level = std::stoi(format);
1053     } catch (const std::invalid_argument &ia) {
1054       MS_LOG(EXCEPTION) << "Invalid argument: " << ia.what() << " when parse " << format
1055                         << ". Please set this env variable to number 0-2.";
1056     }
1057   } else if (format.size() > 1) {
1058     MS_LOG(EXCEPTION) << "MS_DEV_DUMP_IR_FORMAT should be a single number with one digit.";
1059   }
1060 
1061   if (format_level < 0 || format_level > 2) {
1062     MS_LOG(EXCEPTION) << "Format level can only be from 0 to 2";
1063   }
1064 
1065   return format_level;
1066 }
1067 
DumpIRInSubgraph(const std::vector<AnfNodePtr> & nodes,OrderedMap<AnfNodePtr,int32_t> * para_map,OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * const sub_graphs,int32_t total_para,bool dump_full_name,LocDumpMode dump_location)1068 void DumpIRInSubgraph(const std::vector<AnfNodePtr> &nodes, OrderedMap<AnfNodePtr, int32_t> *para_map,
1069                       OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *const sub_graphs, int32_t total_para,
1070                       bool dump_full_name, LocDumpMode dump_location) {
1071   if (para_map == nullptr || sub_graphs == nullptr) {
1072     return;
1073   }
1074 
1075   for (const auto &node : nodes) {
1076     MS_EXCEPTION_IF_NULL(node);
1077     FuncGraphPtr sub_graph = node->func_graph();
1078     if (sub_graph == nullptr) {
1079       MS_LOG(DEBUG) << "Node[" << node->ToString() << "] belongs to no graph!";
1080       continue;
1081     }
1082     std::shared_ptr<SubGraphIRInfo> gsub = (*sub_graphs)[sub_graph];
1083     if (gsub == nullptr) {
1084       gsub = std::make_shared<SubGraphIRInfo>();
1085       gsub->local_var = 0;
1086       gsub->format_level = GetDumpFormatLevel();
1087       (*sub_graphs)[sub_graph] = gsub;
1088     }
1089     std::vector<AnfNodePtr> parameters = sub_graph->parameters();
1090     for (size_t idx = 0; idx < parameters.size(); idx++) {
1091       MS_EXCEPTION_IF_NULL(parameters[idx]);
1092       if ((*para_map).count(parameters[idx]) == 0) {
1093         (*para_map)[parameters[idx]] = total_para++;
1094       }
1095     }
1096     if (!node->isa<Parameter>()) {
1097       if (node->isa<CNode>()) {
1098         // Print and record output of operator if it is not 'Return'
1099         gsub->cnode_num++;
1100         DumpCNode(node->cast<CNodePtr>(), sub_graph, *para_map, gsub, dump_full_name, dump_location);
1101       } else if (AnfUtils::IsCustomActorNode(node)) {
1102         continue;
1103       } else {
1104         gsub->buffer << "  " << node->ToString() << std::endl;
1105       }
1106     }
1107   }
1108 }
1109 
DumpSubgraph(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,const FuncGraphPtr & graph,OrderedMap<AnfNodePtr,int32_t> * para_map,std::ostringstream & oss)1110 void DumpSubgraph(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
1111                   const FuncGraphPtr &graph, OrderedMap<AnfNodePtr, int32_t> *para_map, std::ostringstream &oss) {
1112   if (sub_graphs == nullptr || graph == nullptr) {
1113     return;
1114   }
1115   int format_level = GetDumpFormatLevel();
1116   for (const auto &sg : *sub_graphs) {
1117     MS_EXCEPTION_IF_NULL(sg.first);
1118     if (*(sg.first->indirect())) {
1119       oss << "indirect: " << *(sg.first->indirect()) << "\n";
1120     }
1121     if (format_level > kBasicLevel) {
1122       oss << "subgraph attr:" << std::endl;
1123       for (const auto &attr : sg.first->attrs()) {
1124         oss << attr.first << ": ";
1125         if (attr.second->isa<BoolImm>()) {
1126           oss << GetValue<bool>(attr.second);
1127         } else if (attr.second->isa<StringImm>()) {
1128           oss << (GetValue<std::string>(attr.second));
1129         }
1130         oss << std::endl;
1131       }
1132       if (sg.first->symbol_engine() != nullptr) {
1133         oss << "subgraph symbol engine: " << sg.first->symbol_engine()->ToString() << " : "
1134             << sg.first->symbol_engine().get() << std::endl;
1135       }
1136       oss << "subgraph instance: " << sg.first->ToString() << " : " << sg.first.get() << std::endl;
1137 
1138       // Dump side effect info.
1139       auto effect_info = sg.first->GetEffectInfo();
1140       if (effect_info.HasEffect()) {
1141         oss << "# " << effect_info.ToString() << '\n';
1142       }
1143       // Dump parameters info.
1144       if (sg.first != graph) {
1145         DumpParameters(sg.first, oss);
1146       }
1147     }
1148     if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1149       oss << trace::GetDebugInfoStr(sg.first->debug_info(), "# ", kSourceLineTipDiscard) << "#"
1150           << trace::Label(sg.first->debug_info()) << "\n";
1151     } else {
1152       oss << trace::GetDebugInfoStr(sg.first->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
1153     }
1154     oss << "subgraph @" << sg.first->ToString();
1155     if (sg.first->manager() != nullptr && sg.first->parent() != nullptr) {
1156       oss << " parent: [subgraph @" << sg.first->parent()->ToString() << "]";
1157     }
1158     oss << "(";
1159     if (sg.first != graph) {
1160       std::vector<AnfNodePtr> parameters = sg.first->parameters();
1161       if (parameters.size() == 1) {
1162         MS_EXCEPTION_IF_NULL(parameters[0]);
1163         oss << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
1164       } else if (parameters.size() > 1) {
1165         for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
1166           MS_EXCEPTION_IF_NULL(parameters[idx]);
1167           oss << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
1168           oss << ", ";
1169         }
1170         MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
1171         oss << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
1172             << parameters[parameters.size() - 1]->ToString();
1173       }
1174     }
1175     oss << ") {" << std::endl;
1176     MS_EXCEPTION_IF_NULL(sg.second);
1177     oss << sg.second->buffer.str();
1178     oss << "}" << std::endl;
1179     OutputOrderList(sg.first, oss);
1180     DumpSymbolEngine(sg.first, oss, format_level);
1181     oss << std::endl;
1182     oss << std::endl;
1183   }
1184 }
1185 
SetDumpConfigByString(const std::string & str,DumpConfig * dump_config)1186 void SetDumpConfigByString(const std::string &str, DumpConfig *dump_config) {
1187   MS_LOG(INFO) << "Set dump config:" << str;
1188   static mindspore::HashMap<std::string, enum LocDumpMode> dump_level_map = {
1189     {kDumpConfigLineLevel0, kOff}, {kDumpConfigLineLevel1, kTopStack}, {kDumpConfigLineLevel2, kWholeStack}};
1190   auto it = dump_level_map.find(str);
1191   if (it != dump_level_map.end()) {
1192     dump_config->dump_line_level = it->second;
1193     return;
1194   }
1195   if (str == kDumpConfigDisableBackend) {
1196     dump_config->disable_backend_dump = true;
1197     return;
1198   }
1199   if (str == kDumpConfigEnablePassIR) {
1200     dump_config->enable_dump_pass_ir = true;
1201     return;
1202   }
1203 }
1204 
GetAllConfigStrings(const std::string & config_full_string)1205 std::shared_ptr<OrderedSet<std::string>> GetAllConfigStrings(const std::string &config_full_string) {
1206   size_t start_pos = 0;
1207   auto config_strings = std::make_shared<OrderedSet<std::string>>();
1208   // if '#' is the last char of str, the str is legal, so we use '<=' but not '<'.
1209   while (start_pos <= config_full_string.size()) {
1210     auto pos = config_full_string.find('#', start_pos);
1211     if (pos == std::string::npos) {
1212       pos = config_full_string.size();
1213     }
1214     auto substr = config_full_string.substr(start_pos, pos - start_pos);
1215     // Skip the '#'
1216     start_pos = pos + 1;
1217     if (substr.empty()) {
1218       continue;
1219     }
1220     (void)config_strings->insert(substr);
1221   }
1222   return config_strings;
1223 }
1224 
ConfigsAreLegal(const std::shared_ptr<OrderedSet<std::string>> & config_strings)1225 bool ConfigsAreLegal(const std::shared_ptr<OrderedSet<std::string>> &config_strings) {
1226   // Value 'int' is used to mark config group id
1227   HashMap<std::string, int> config_white_list = {{kDumpConfigLineLevel0, 0},
1228                                                  {kDumpConfigLineLevel1, 0},
1229                                                  {kDumpConfigLineLevel2, 0},
1230                                                  {kDumpConfigDisableBackend, 1},
1231                                                  {kDumpConfigEnablePassIR, 2}};
1232   // Key 'int' is config group id, value is the config.
1233   HashMap<int, std::string> config_groups;
1234   for (const auto &config_string : *config_strings) {
1235     auto config_white_list_it = config_white_list.find(config_string);
1236     if (config_white_list_it == config_white_list.end()) {
1237       std::ostringstream buffer;
1238       buffer << "Support configs:\n"
1239              << "[0]: " << kDumpConfigLineLevel0 << "\n"
1240              << "[1]: " << kDumpConfigLineLevel1 << "\n"
1241              << "[2]: " << kDumpConfigLineLevel2 << "\n"
1242              << "[3]: " << kDumpConfigDisableBackend << "\n"
1243              << "[4]: " << kDumpConfigEnablePassIR;
1244       MS_LOG(WARNING) << "Illegal dump config:\n" << config_string << "\n" << buffer.str();
1245       return false;
1246     }
1247     auto group_id = config_white_list_it->second;
1248     // Check conflict configs.
1249     auto config_groups_it = config_groups.find(group_id);
1250     if (config_groups_it != config_groups.end()) {
1251       const auto &record_config = config_groups_it->second;
1252       MS_LOG(WARNING) << "Dump configs are conflict. Conflict configs: [" << record_config << "] and [" << config_string
1253                       << "].\n"
1254                       << "Please keep only one of them.";
1255       return false;
1256     }
1257     config_groups[group_id] = config_string;
1258   }
1259   return true;
1260 }
1261 
GetDumpConfig()1262 DumpConfig GetDumpConfig() {
1263   static DumpConfig dump_config = DumpConfig();
1264   static bool parsed = false;
1265   if (parsed) {
1266     return dump_config;
1267   }
1268   parsed = true;
1269   // Start parse config.
1270   std::string str(common::GetCompileConfig("DUMP_IR_CONFIG"));
1271   auto constexpr max_string_len = 100;
1272   if (str.size() > max_string_len) {
1273     MS_LOG(WARNING) << "Dump ir config length exceed max length: " << max_string_len;
1274     return dump_config;
1275   }
1276   if (str.empty()) {
1277     return dump_config;
1278   }
1279   auto config_strings = GetAllConfigStrings(str);
1280   if (!ConfigsAreLegal(config_strings)) {
1281     return dump_config;
1282   }
1283   for (const auto &config : *config_strings) {
1284     SetDumpConfigByString(config, &dump_config);
1285   }
1286   return dump_config;
1287 }
1288 
GetEnvDumpIrLineLevel(LocDumpMode * dump_location)1289 void GetEnvDumpIrLineLevel(LocDumpMode *dump_location) {
1290   const auto &config = GetDumpConfig();
1291   if (config.dump_line_level != kInValid) {
1292     *dump_location = config.dump_line_level;
1293   }
1294 }
1295 
DumpNodeCounting(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,std::ostringstream & oss,const std::vector<AnfNodePtr> & nodes)1296 void DumpNodeCounting(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
1297                       std::ostringstream &oss, const std::vector<AnfNodePtr> &nodes) {
1298   oss << "Node counting information:" << std::endl;
1299   oss << "Total number of nodes: " << nodes.size() << std::endl;
1300   auto total_cnode =
1301     std::accumulate((*sub_graphs).cbegin(), (*sub_graphs).cend(), 0,
1302                     [](const int32_t previous, const std::pair<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> &pair) {
1303                       return previous + pair.second->cnode_num;
1304                     });
1305   oss << "Total number of cnodes: " << total_cnode << std::endl;
1306   oss << std::endl;
1307 }
1308 
SaveIRFile(const std::string & filename,const std::string & str,const std::string & target_file)1309 void SaveIRFile(const std::string &filename, const std::string &str, const std::string &target_file) {
1310   std::string path;
1311   if (!target_file.empty()) {
1312     path = target_file;
1313   } else {
1314     path = GetSaveGraphsPathName(filename);
1315   }
1316   auto realpath = Common::CreatePrefixPath(path);
1317   if (!realpath.has_value()) {
1318     MS_LOG(ERROR) << "Get real path failed, path=" << path;
1319     return;
1320   }
1321 
1322   ChangeFileMode(realpath.value(), S_IWUSR);
1323   std::ofstream fout(realpath.value());
1324   if (!fout.is_open()) {
1325     MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1326     return;
1327   }
1328 
1329   // Output all content.
1330   fout << str;
1331   fout.close();
1332   // Set file mode to read only by user
1333   ChangeFileMode(realpath.value(), S_IRUSR);
1334 }
1335 
1336 #ifdef ENABLE_DUMP_IR
ToJson(const CNodePtr & para_node,const int64_t global_rank_id,std::unordered_map<std::string,std::vector<uint32_t>> group_map)1337 nlohmann::ordered_json ToJson(const CNodePtr &para_node, const int64_t global_rank_id,
1338                               std::unordered_map<std::string, std::vector<uint32_t>> group_map) {
1339   nlohmann::ordered_json args;
1340   MS_EXCEPTION_IF_NULL(para_node);
1341   auto abs = para_node->abstract();
1342   MS_EXCEPTION_IF_NULL(abs);
1343   auto prim = GetCNodePrimitive(para_node);
1344   MS_EXCEPTION_IF_NULL(prim);
1345   args["op_name"] = para_node->UniqueName();
1346   args["op_type"] = prim->name();
1347   args["shape"] = abs->BuildShape()->ToString();
1348   args["data_type"] = abs->BuildType()->ToString();
1349   args["global_rank_id"] = std::to_string(global_rank_id);
1350   std::string group_name = "";
1351   std::string group = "group";
1352   if (prim->HasAttr(group)) {
1353     group_name = GetValue<std::string>(prim->GetAttr(group));
1354   }
1355   args["comm_group_name"] = group_name;
1356   if (prim->HasAttr(kAttrGroupRankIds)) {
1357     auto value_ptr = prim->GetAttr(kAttrGroupRankIds);
1358     args["comm_group_rank_ids"] = value_ptr->ToString();
1359     if (group_map.find(group_name) != group_map.end()) {
1360       std::ostringstream oss;
1361       oss << "(";
1362       const std::vector<uint32_t> group_ranks = group_map[group_name];
1363       (void)std::copy(group_ranks.begin(), group_ranks.end() - 1, std::ostream_iterator<int>(oss, ","));
1364       oss << group_ranks.back() << ")";
1365       args["comm_group_rank_ids"] = oss.str();
1366     }
1367   }
1368   if (prim->HasAttr(kAttrSrcRank) && prim->HasAttr(kAttrSrTag)) {
1369     args["src_rank"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrcRank)));
1370     args["sr_tag"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrTag)));
1371   }
1372   if (prim->HasAttr(kAttrDestRank) && prim->HasAttr(kAttrSrTag)) {
1373     args["dest_rank"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrDestRank)));
1374     args["sr_tag"] = std::to_string(GetValue<int64_t>(prim->GetAttr(kAttrSrTag)));
1375   }
1376   return args;
1377 }
1378 
DumpParallelInfo(const FuncGraphPtr & graph,size_t * op_id,nlohmann::ordered_json * args,const int64_t global_rank_id,const std::unordered_map<std::string,std::vector<uint32_t>> & group_map)1379 void DumpParallelInfo(const FuncGraphPtr &graph, size_t *op_id, nlohmann::ordered_json *args,
1380                       const int64_t global_rank_id,
1381                       const std::unordered_map<std::string, std::vector<uint32_t>> &group_map) {
1382   MS_EXCEPTION_IF_NULL(graph);
1383   std::list<CNodePtr> graph_orders = graph->GetOrderedCnodes();
1384   for (auto &node : graph_orders) {
1385     MS_EXCEPTION_IF_NULL(node);
1386     if (IsValueNode<FuncGraph>(node->input(0))) {
1387       FuncGraphPtr sub_graph = node->input(0)->cast<ValueNodePtr>()->value()->cast<FuncGraphPtr>();
1388       DumpParallelInfo(sub_graph, op_id, args, global_rank_id, group_map);
1389     } else if (common::AnfAlgo::IsCommunicationOp(node)) {
1390       (*args)[std::to_string(*op_id)] = ToJson(node, global_rank_id, group_map);
1391       *op_id = *op_id + 1;
1392     } else if (node->input(0)->isa<CNode>() && node->input(0)->abstract() != nullptr) {
1393       auto abs = node->input(0)->abstract();
1394       if (abs->isa<abstract::FuncGraphAbstractClosure>()) {
1395         const auto &abstract_func_graph = abs->cast<abstract::FuncGraphAbstractClosurePtr>();
1396         MS_EXCEPTION_IF_NULL(abstract_func_graph->func_graph());
1397         DumpParallelInfo(abstract_func_graph->func_graph(), op_id, args, global_rank_id, group_map);
1398       } else if (abs->isa<abstract::PartialAbstractClosure>()) {
1399         const auto &abstract_partial_func = abs->cast<abstract::PartialAbstractClosurePtr>();
1400         const auto &abstract_fn = abstract_partial_func->fn();
1401         if (abstract_fn->isa<abstract::FuncGraphAbstractClosure>()) {
1402           const auto &abstract_func_graph = abstract_fn->cast<abstract::FuncGraphAbstractClosurePtr>();
1403           MS_EXCEPTION_IF_NULL(abstract_func_graph->func_graph());
1404           DumpParallelInfo(abstract_func_graph->func_graph(), op_id, args, global_rank_id, group_map);
1405         }
1406       }
1407     }
1408   }
1409 }
1410 
DumpParallelJson(const std::string & filename,const FuncGraphPtr & graph,const int64_t global_rank_id,const std::unordered_map<std::string,std::vector<uint32_t>> & group_map)1411 void DumpParallelJson(const std::string &filename, const FuncGraphPtr &graph, const int64_t global_rank_id,
1412                       const std::unordered_map<std::string, std::vector<uint32_t>> &group_map) {
1413   if (graph == nullptr) {
1414     return;
1415   }
1416   std::string save_path = "";
1417   if (!common::GetEnv("MA_LOG_DIR").empty()) {
1418     save_path = common::GetEnv("MA_LOG_DIR");
1419   }
1420   auto path = GetSaveGraphsPathName(filename, save_path);
1421   auto realpath = Common::CreatePrefixPath(path);
1422   if (!realpath.has_value()) {
1423     MS_LOG(ERROR) << "Get real path failed, path is " << path;
1424     return;
1425   }
1426 
1427   ChangeFileMode(realpath.value(), S_IWUSR);
1428   std::ofstream fout(realpath.value());
1429   if (!fout.is_open()) {
1430     MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1431     return;
1432   }
1433   size_t op_id = 0;
1434   nlohmann::ordered_json args;
1435   args["hccl_algo"] = common::GetEnv("HCCL_ALGO");
1436   DumpParallelInfo(graph, &op_id, &args, global_rank_id, group_map);
1437   constexpr size_t json_dump_mode = 2;
1438   fout << args.dump(json_dump_mode);
1439 
1440   fout.close();
1441   // Set file mode to read only by user
1442   ChangeFileMode(realpath.value(), S_IRUSR);
1443 }
1444 
DumpIRHead(const FuncGraphPtr & top_func,std::ostringstream & ofs)1445 void DumpIRHead(const FuncGraphPtr &top_func, std::ostringstream &ofs) {
1446   MS_EXCEPTION_IF_NULL(top_func);
1447   auto sub_graphs = top_func->func_graphs_used_total();
1448   DumpGlobalInfoEntry(top_func, ofs, sub_graphs.size());
1449   OrderedMap<AnfNodePtr, int32_t> para_map;
1450   (void)DumpParams(top_func, ofs, &para_map);
1451   ofs << std::endl;
1452 }
1453 
DumpIR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location,const std::string & target_file)1454 void DumpIR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name, LocDumpMode dump_location,
1455             const std::string &target_file) {
1456   if (graph == nullptr) {
1457     return;
1458   }
1459   // Id auto increment in AddId(), and CheckIfPrintIrPass() would check id, so we call AddId() in advance.
1460   auto filename_with_id = Common::AddId(filename, ".ir");
1461   bool need_dump = Common::CheckIfPrintIrPass(filename);
1462   if (!need_dump) {
1463     return;
1464   }
1465 
1466   std::ostringstream out_oss;
1467   DumpIR(out_oss, graph, dump_full_name, dump_location, false);
1468   SaveIRFile(filename_with_id, out_oss.str(), target_file);
1469 }
1470 
DumpIR(std::ostringstream & out_oss,const FuncGraphPtr & graph,bool dump_full_name,int dump_location,bool avoid_circle)1471 void DumpIR(std::ostringstream &out_oss, const FuncGraphPtr &graph, bool dump_full_name, int dump_location,
1472             bool avoid_circle) {
1473   if (graph == nullptr) {
1474     return;
1475   }
1476   auto nodes =
1477     TopoSort(graph->get_return(), avoid_circle ? SuccIncoming : SuccDeeperSimple, AlwaysInclude, avoid_circle);
1478 
1479   OrderedMap<AnfNodePtr, int32_t> para_map;
1480   std::ostringstream param_oss;
1481   int32_t total_para = DumpParams(graph, param_oss, &para_map);
1482   OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
1483   // Check If update dump_location option by compile config
1484   GetEnvDumpIrLineLevel(reinterpret_cast<LocDumpMode *>(&dump_location));
1485   // Output ir in each sub graph
1486   DumpIRInSubgraph(nodes, &para_map, &sub_graphs, total_para, dump_full_name, static_cast<LocDumpMode>(dump_location));
1487 
1488   if (!avoid_circle) {
1489     // Output global info
1490     DumpGlobalInfoEntry(graph, out_oss, sub_graphs.size());
1491     // Output parameters info
1492     out_oss << param_oss.str();
1493   }
1494 
1495   // Add counting information for nodes
1496   out_oss << std::endl;
1497   DumpNodeCounting(&sub_graphs, out_oss, nodes);
1498 
1499   // Output each sub graph
1500   DumpSubgraph(&sub_graphs, graph, &para_map, out_oss);
1501 }
1502 
DumpIRForRDR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location)1503 void DumpIRForRDR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name,
1504                   LocDumpMode dump_location) {
1505   if (graph == nullptr) {
1506     return;
1507   }
1508   auto path = Common::AddId(filename, ".ir");
1509   bool need_dump = Common::CheckIfPrintIrPass(filename);
1510   if (!need_dump) {
1511     return;
1512   }
1513   auto realpath = Common::CreatePrefixPath(path);
1514   if (!realpath.has_value()) {
1515     MS_LOG(ERROR) << "Get real path failed. path=" << path;
1516     return;
1517   }
1518 
1519   ChangeFileMode(realpath.value(), S_IWUSR);
1520   std::ofstream fout(realpath.value());
1521   std::ostringstream buffer;
1522   if (!fout.is_open()) {
1523     MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
1524     return;
1525   }
1526 
1527   auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
1528   OrderedMap<AnfNodePtr, int32_t> para_map;
1529   int32_t total_para = DumpParams(graph, buffer, &para_map);
1530   OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
1531   GetEnvDumpIrLineLevel(&dump_location);
1532   // Dump ir in each sub graph
1533   DumpIRInSubgraph(nodes, &para_map, &sub_graphs, total_para, dump_full_name, dump_location);
1534   // Add counting information for nodes
1535   buffer << std::endl;
1536   DumpNodeCounting(&sub_graphs, buffer, nodes);
1537   // Dump global info
1538   DumpGlobalInfoEntry(graph, buffer, sub_graphs.size());
1539   // Output global info
1540   fout << buffer.str() << std::endl;
1541   buffer.str(std::string());
1542   buffer.clear();
1543 
1544   // Output each sub graph
1545   DumpSubgraph(&sub_graphs, graph, &para_map, buffer);
1546   fout << buffer.str();
1547 
1548   fout.close();
1549   // Set file mode to read only by user
1550   ChangeFileMode(realpath.value(), S_IRUSR);
1551 }
1552 #else
DumpIR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode,const std::string &,bool)1553 void DumpIR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode, const std::string &, bool) {
1554   static bool already_printed = false;
1555   if (already_printed) {
1556     return;
1557   }
1558   already_printed = true;
1559   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1560                   << "please recompile source to enable it. See help of building script.";
1561 }
1562 
DumpIR(std::ostringstream &,const FuncGraphPtr &,bool,int,bool)1563 void DumpIR(std::ostringstream &, const FuncGraphPtr &, bool, int, bool) {
1564   static bool already_printed = false;
1565   if (already_printed) {
1566     return;
1567   }
1568   already_printed = true;
1569   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1570                   << "please recompile source to enable it. See help of building script.";
1571 }
1572 
DumpIRForRDR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode)1573 void DumpIRForRDR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode) {
1574   static bool already_printed = false;
1575   if (already_printed) {
1576     return;
1577   }
1578   already_printed = true;
1579   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1580                   << "please recompile source to enable it. See help of building script.";
1581 }
1582 #endif
1583 
OuputIrStyleCNodes(const FuncGraphPtr & func_graph,const std::vector<AnfNodePtr> & nodes,int32_t total_para,std::ostringstream & oss,OrderedMap<AnfNodePtr,int32_t> * para_map)1584 void AnfExporter::OuputIrStyleCNodes(const FuncGraphPtr &func_graph, const std::vector<AnfNodePtr> &nodes,
1585                                      int32_t total_para, std::ostringstream &oss,
1586                                      OrderedMap<AnfNodePtr, int32_t> *para_map) {
1587   MS_EXCEPTION_IF_NULL(func_graph);
1588   auto &parameters = func_graph->parameters();
1589   std::shared_ptr<SubGraphIRInfo> gsub = std::make_shared<SubGraphIRInfo>();
1590   ParamIndexMap param_map;
1591   exported_[func_graph] = param_map;
1592   gsub->local_var = 0;
1593   gsub->format_level = GetDumpFormatLevel();
1594   for (size_t idx = 0; idx < parameters.size(); idx++) {
1595     MS_EXCEPTION_IF_NULL(parameters[idx]);
1596     if ((*para_map).count(parameters[idx]) == 0) {
1597       (*para_map)[parameters[idx]] = total_para++;
1598     }
1599   }
1600   for (const AnfNodePtr &node : nodes) {
1601     MS_EXCEPTION_IF_NULL(node);
1602     if (!node->isa<CNode>()) {
1603       continue;
1604     }
1605     auto cnode = node->cast<CNodePtr>();
1606     auto &inputs = cnode->inputs();
1607     for (size_t i = 0; i < inputs.size(); ++i) {
1608       if (IsValueNode<FuncGraph>(inputs[i])) {
1609         FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(inputs[i]);
1610         if (!func_graph_set_.contains(fg) && exported_.find(fg) == exported_.end() && export_used_) {
1611           func_graph_set_.add(fg);
1612         }
1613       }
1614     }
1615     DumpCNode(cnode, func_graph, *para_map, gsub);
1616     if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1617       gsub->buffer << trace::GetDebugInfoStr(cnode->debug_info(), "      # ", kSourceLineTipDiscard) << "#"
1618                    << trace::Label(cnode->debug_info()) << "\n";
1619     } else {
1620       std::string dgi = trace::GetDebugInfoStr(cnode->debug_info(), "      # ", kSourceLineTipDiscard);
1621       if (dgi != "") {
1622         gsub->buffer << trace::GetDebugInfoStr(cnode->debug_info(), "      # ", kSourceLineTipDiscard) << "\n";
1623       }
1624     }
1625   }
1626   if (!is_top_graph_) {
1627     if (parameters.size() == 1) {
1628       MS_EXCEPTION_IF_NULL(parameters[0]);
1629       oss << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
1630     } else if (parameters.size() > 1) {
1631       for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
1632         MS_EXCEPTION_IF_NULL(parameters[idx]);
1633         oss << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
1634         oss << ", ";
1635       }
1636       MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
1637       oss << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
1638           << parameters[parameters.size() - 1]->ToString();
1639     }
1640   } else {
1641     is_top_graph_ = false;
1642   }
1643   oss << ") {\n";
1644   oss << gsub->buffer.str();
1645 }
1646 
ExportOneFuncGraph(const FuncGraphPtr & func_graph,const TaggedNodeMap & tagged_cnodes_map,std::ostringstream & oss,int32_t total_para,OrderedMap<AnfNodePtr,int32_t> * para_map)1647 void AnfExporter::ExportOneFuncGraph(const FuncGraphPtr &func_graph, const TaggedNodeMap &tagged_cnodes_map,
1648                                      std::ostringstream &oss, int32_t total_para,
1649                                      OrderedMap<AnfNodePtr, int32_t> *para_map) {
1650   if (func_graph == nullptr) {
1651     return;
1652   }
1653 
1654   std::vector<AnfNodePtr> nodes = TopoSort(func_graph->get_return(), SuccIncoming, AlwaysInclude);
1655 
1656   if (*(func_graph->indirect())) {
1657     oss << "indirect: " << *(func_graph->indirect()) << "\n";
1658   }
1659   oss << "subgraph attr:" << std::endl;
1660   for (const auto &attr : func_graph->attrs()) {
1661     oss << attr.first << ": ";
1662     MS_EXCEPTION_IF_NULL(attr.second);
1663     if (attr.second->isa<BoolImm>()) {
1664       oss << GetValue<bool>(attr.second);
1665     } else if (attr.second->isa<StringImm>()) {
1666       oss << (GetValue<std::string>(attr.second));
1667     }
1668     oss << std::endl;
1669   }
1670   oss << "subgraph instance: " << func_graph->ToString() << " : " << func_graph.get() << std::endl;
1671   // Dump side effect info.
1672   auto effect_info = func_graph->GetEffectInfo();
1673   if (effect_info.HasEffect()) {
1674     oss << "# " << effect_info.ToString() << '\n';
1675   }
1676   // Dump parameters info.
1677   DumpParameters(func_graph, oss);
1678   if (trace::GetGlobalTraceLabelType() == trace::TraceLabelType::kWithUniqueId) {
1679     oss << trace::GetDebugInfoStr(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "#"
1680         << trace::Label(func_graph->debug_info()) << "\n";
1681   } else {
1682     oss << trace::GetDebugInfoStr(func_graph->debug_info(), "# ", kSourceLineTipDiscard) << "\n";
1683   }
1684   oss << "subgraph @" << func_graph->ToString();
1685   if (func_graph->parent() != nullptr) {
1686     oss << " parent: [subgraph @" << func_graph->parent()->ToString() << "]";
1687   }
1688   oss << "(";
1689   OuputIrStyleCNodes(func_graph, nodes, total_para, oss, para_map);
1690 
1691   oss << "}\n";
1692 
1693   OutputOrderList(func_graph, oss);
1694 }
1695 
ExportGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer,int graph_size)1696 void ExportGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer, int graph_size) {
1697   if (graph == nullptr) {
1698     return;
1699   }
1700 
1701   buffer << "# IR entry: @" << graph->ToString() << std::endl;
1702   buffer << "# Total subgraph: " << graph_size;
1703   buffer << std::endl;
1704   buffer << std::endl;
1705   buffer << "# attrs: " << std::endl;
1706   for (const auto &attr : graph->attrs()) {
1707     buffer << attr.first << ": ";
1708     MS_EXCEPTION_IF_NULL(attr.second);
1709     if (attr.second->isa<BoolImm>()) {
1710       buffer << GetValue<bool>(attr.second);
1711     } else if (attr.second->isa<StringImm>()) {
1712       buffer << (GetValue<std::string>(attr.second));
1713     }
1714     buffer << std::endl;
1715   }
1716 }
1717 
ExportFuncGraph(const std::string & filename,const FuncGraphPtr & func_graph)1718 void AnfExporter::ExportFuncGraph(const std::string &filename, const FuncGraphPtr &func_graph) {
1719   if (func_graph == nullptr) {
1720     return;
1721   }
1722 
1723   std::ofstream ofs(filename);
1724   if (!ofs.is_open()) {
1725     MS_LOG(ERROR) << "Open file '" << filename << "' failed!" << ErrnoToString(errno);
1726     return;
1727   }
1728 
1729   param_index_ = 1;
1730   int graph_size = 0;
1731   std::ostringstream oss;
1732   std::ostringstream paramoss;
1733   TaggedNodeMap tagged_cnodes_map;
1734   OrderedMap<AnfNodePtr, int32_t> para_map;
1735   int32_t total_para = DumpParams(func_graph, paramoss, &para_map);
1736   func_graph_set_.add(func_graph);
1737   is_top_graph_ = true;
1738   while (!func_graph_set_.empty()) {
1739     FuncGraphPtr fg = *func_graph_set_.cbegin();
1740     ExportOneFuncGraph(fg, tagged_cnodes_map, oss, total_para, &para_map);
1741     oss << "\n\n";
1742     (void)func_graph_set_.erase(fg);
1743     graph_size++;
1744   }
1745   std::ostringstream buffer;
1746   ExportGlobalInfoEntry(func_graph, buffer, graph_size);
1747   ofs << buffer.str() << paramoss.str() << "\n" << oss.str();
1748   ofs.close();
1749 }
1750 
1751 #ifdef ENABLE_DUMP_IR
ExportIR(const std::string & filename,const FuncGraphPtr & func_graph)1752 void ExportIR(const std::string &filename, const FuncGraphPtr &func_graph) {
1753   bool need_dump = Common::CheckIfPrintIrPass(filename);
1754   if (func_graph == nullptr) {
1755     return;
1756   }
1757   if (!need_dump) {
1758     return;
1759   }
1760 
1761   auto filepath = GetSaveGraphsPathName(Common::AddId(filename, ".ir"));
1762   auto real_filepath = Common::CreatePrefixPath(filepath);
1763   if (!real_filepath.has_value()) {
1764     MS_LOG(ERROR) << "The export ir path: " << filepath << " is not illegal.";
1765     return;
1766   }
1767   ChangeFileMode(real_filepath.value(), S_IWUSR);
1768   AnfExporter exporter;
1769   exporter.ExportFuncGraph(real_filepath.value(), func_graph);
1770   // Set file mode to read only by user
1771   ChangeFileMode(real_filepath.value(), S_IRUSR);
1772 }
1773 #else
ExportIR(const std::string &,const FuncGraphPtr &)1774 void ExportIR(const std::string &, const FuncGraphPtr &) {
1775   static bool already_printed = false;
1776   if (already_printed) {
1777     return;
1778   }
1779   already_printed = true;
1780   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
1781                   << "please recompile to enable it. See help of building script.";
1782 }
1783 #endif
1784 
1785 #ifdef ENABLE_DUMP_IR
1786 // Register DumpIR Privider.
1787 struct DumpIRPrividerRegister {
DumpIRPrividerRegistermindspore::DumpIRPrividerRegister1788   DumpIRPrividerRegister() noexcept {
1789     DumpIRPrividerFunction func = &DumpIR;
1790     SetDumpIRPrivider(func);
1791   }
1792   ~DumpIRPrividerRegister() = default;
1793 } dump_ir_provider_register;
1794 
1795 // Register DumpIR Storage.
1796 struct DumpIRStorageRegister {
DumpIRStorageRegistermindspore::DumpIRStorageRegister1797   DumpIRStorageRegister() noexcept {
1798     DumpIRStorageFunction func = &SaveIRFile;
1799     SetDumpIRStorage(func);
1800   }
1801   ~DumpIRStorageRegister() = default;
1802 } dump_ir_storage_register;
1803 #endif
1804 }  // namespace mindspore
1805