• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2019-2021 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 "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 <memory>
23 #include <unordered_map>
24 #include "ir/primitive.h"
25 #include "ir/func_graph.h"
26 #include "runtime/device/kernel_info.h"
27 #include "ir/graph_utils.h"
28 #include "backend/session/anf_runtime_algorithm.h"
29 #include "frontend/parallel/ops_info/operator_info.h"
30 #include "pipeline/jit/base.h"
31 #include "debug/trace.h"
32 #include "utils/trace_base.h"
33 
34 namespace mindspore {
ToShortString(const TypeId & typeId)35 const std::string ToShortString(const TypeId &typeId) {
36   std::string label = TypeIdLabel(typeId);
37   std::string prefix = "kNumberType";
38   if (prefix.length() > label.length()) {
39     return label;
40   }
41   auto position = label.find(prefix);
42   // position is 0 when label begins with prefix
43   if (position != 0) {
44     return label;
45   }
46   auto sub_position = position + prefix.length();
47   if (sub_position >= label.length()) {
48     return label;
49   }
50   return label.substr(sub_position);
51 }
52 
PrintKernelFormatAndType(std::ostringstream & buffer,const std::string & fmt,const TypeId & type,const std::vector<size_t> & shape)53 void PrintKernelFormatAndType(std::ostringstream &buffer, const std::string &fmt, const TypeId &type,
54                               const std::vector<size_t> &shape) {
55   buffer << "<" << ToShortString(type);
56   if (!fmt.empty()) {
57     buffer << "x" << fmt << shape;
58   }
59   buffer << ">";
60 }
61 
PrintNodeOutputType(std::ostringstream & buffer,const AnfNodePtr & nd)62 void PrintNodeOutputType(std::ostringstream &buffer, const AnfNodePtr &nd) {
63   if (nd == nullptr) {
64     return;
65   }
66 
67   ValuePtr tensor_value = nullptr;
68   auto abstract = nd->abstract();
69   if (abstract != nullptr && abstract->isa<abstract::AbstractTensor>()) {
70     tensor_value = abstract->BuildValue();
71   }
72   abstract::ShapePtr shape = dyn_cast<abstract::Shape>(nd->Shape());
73   TypePtr type = dyn_cast<Type>(nd->Type());
74   if ((shape != nullptr) && (type != nullptr)) {
75     buffer << "<" << type << ", " << shape->ToString();
76     if (tensor_value != nullptr && tensor_value != kAnyValue) {
77       buffer << ", value=...";
78     }
79     buffer << ">";
80   } else if (type != nullptr) {
81     buffer << "<" << type;
82     if (tensor_value != nullptr && tensor_value != kAnyValue) {
83       buffer << ", value=...";
84     }
85     buffer << ">";
86   } else {
87     buffer << "<null>";
88   }
89 }
90 
PrintNodeInputType(std::ostringstream & buffer,const AnfNodePtr & nd)91 void PrintNodeInputType(std::ostringstream &buffer, const AnfNodePtr &nd) {
92   if (nd == nullptr) {
93     return;
94   }
95 
96   const auto &inputs = GetInputs(nd);
97   size_t len = inputs.size();
98   if (len > 1) {
99     // skip inputs[0] which is Primitive value node
100     for (size_t i = 1; i < len; ++i) {
101       AnfNodePtr in = inputs[i];
102       if (i != 1) {
103         buffer << ", ";
104       }
105       PrintNodeOutputType(buffer, in);
106     }
107   }
108 }
109 
PrintInputAndOutputInferType(std::ostringstream & buffer,const AnfNodePtr & nd)110 void PrintInputAndOutputInferType(std::ostringstream &buffer, const AnfNodePtr &nd) {
111   buffer << "      : (";
112   PrintNodeInputType(buffer, nd);
113   buffer << ") -> (";
114   PrintNodeOutputType(buffer, nd);
115   buffer << ")";
116 }
117 
118 struct SubGraphIRInfo {
119   int32_t local_var;
120   std::ostringstream buffer;
121   OrderedMap<AnfNodePtr, int32_t> local_var_map;
122 };
123 
DumpGlobalInfoEntry(const FuncGraphPtr & graph,std::ostringstream & buffer)124 void DumpGlobalInfoEntry(const FuncGraphPtr &graph, std::ostringstream &buffer) {
125   if (graph == nullptr) {
126     return;
127   }
128 
129   buffer << "#IR entry      : @" << graph->ToString() << std::endl;
130   buffer << "#attrs         :" << std::endl;
131   for (const auto &attr : graph->attrs()) {
132     buffer << attr.first << " : ";
133     if (attr.second->isa<BoolImm>()) {
134       buffer << GetValue<bool>(attr.second);
135     } else if (attr.second->isa<StringImm>()) {
136       buffer << GetValue<std::string>(attr.second);
137     }
138     buffer << std::endl;
139   }
140 }
141 
DumpKernelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)142 void DumpKernelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
143   if (node == nullptr || gsub == nullptr) {
144     return;
145   }
146   auto kernel_info = node->kernel_info();
147   if (kernel_info == nullptr || !kernel_info->has_build_info()) {
148     return;
149   }
150 
151   gsub->buffer << "      : (";
152   size_t input_num = AnfAlgo::GetInputTensorNum(node);
153   for (size_t i = 0; i < input_num; ++i) {
154     if (i != 0) {
155       gsub->buffer << ", ";
156     }
157     auto format = AnfAlgo::GetInputFormat(node, i);
158     auto type = AnfAlgo::GetInputDeviceDataType(node, i);
159     auto shape = AnfAlgo::GetInputDeviceShape(node, i);
160     PrintKernelFormatAndType(gsub->buffer, format, type, shape);
161   }
162   gsub->buffer << ") -> (";
163   size_t output_num = AnfAlgo::GetOutputTensorNum(node);
164   for (size_t i = 0; i < output_num; ++i) {
165     if (i != 0) {
166       gsub->buffer << ", ";
167     }
168     auto format = AnfAlgo::GetOutputFormat(node, i);
169     auto type = AnfAlgo::GetOutputDeviceDataType(node, i);
170     auto shape = AnfAlgo::GetOutputDeviceShape(node, i);
171     PrintKernelFormatAndType(gsub->buffer, format, type, shape);
172   }
173   gsub->buffer << ")";
174   gsub->buffer << std::endl;
175 }
176 
DumpParams(const FuncGraphPtr & graph,std::ostringstream & buffer,OrderedMap<AnfNodePtr,int32_t> * para_map)177 int32_t DumpParams(const FuncGraphPtr &graph, std::ostringstream &buffer, OrderedMap<AnfNodePtr, int32_t> *para_map) {
178   if (graph == nullptr) {
179     MS_LOG(INFO) << "Param graph is nullptr.";
180     return 0;
181   }
182   std::vector<AnfNodePtr> parameters = graph->parameters();
183   buffer << "#Total params  : " << parameters.size() << std::endl;
184   buffer << std::endl;
185 
186   // dump parameters
187   int32_t para = 1;
188   for (const auto &p : parameters) {
189     if (p == nullptr) {
190       continue;
191     }
192     auto parameter_ptr = p->cast<ParameterPtr>();
193     if (parameter_ptr == nullptr) {
194       MS_LOG(EXCEPTION) << "p cannot cast to ParameterPtr";
195     }
196     buffer << "%para" << para << "_" << parameter_ptr->name() << " : ";
197     // print parameters' type and shape
198     PrintNodeOutputType(buffer, p);
199     auto kernel_info = p->kernel_info();
200     if (kernel_info != nullptr && kernel_info->has_build_info()) {
201       buffer << "  :  ";
202       auto type = AnfAlgo::GetOutputDeviceDataType(p, 0);
203       auto format = AnfAlgo::GetOutputFormat(p, 0);
204       auto shape = AnfAlgo::GetOutputDeviceShape(p, 0);
205       PrintKernelFormatAndType(buffer, format, type, shape);
206       buffer << "  :  IsWeight:" << std::boolalpha << AnfAlgo::IsParameterWeight(parameter_ptr);
207     }
208     buffer << std::endl;
209 
210     if (para_map != nullptr) {
211       (*para_map)[p] = para++;
212     }
213     MS_LOG(DEBUG) << "Record param: " << p->ToString() << " graph belong : " << p->func_graph()->ToString();
214   }
215   return para;
216 }
217 
DumpOperator(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)218 void DumpOperator(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
219   if (op == nullptr) {
220     MS_LOG(INFO) << "Param op is nullptr";
221     return;
222   }
223   if (gsub == nullptr) {
224     MS_LOG(INFO) << "Param gsub is nullptr";
225     return;
226   }
227 
228   if (IsValueNode<FuncGraph>(op)) {
229     FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(op);
230     if (fg != nullptr) {
231       gsub->buffer << "call @" << fg->ToString();
232     }
233   } else if (op->isa<CNode>()) {
234     if (gsub->local_var_map.find(op) != gsub->local_var_map.end()) {
235       gsub->buffer << "%" << gsub->local_var_map[op];
236     } else {
237       auto node = op->cast<CNodePtr>();
238       auto fg = node->func_graph();
239       gsub->buffer << "$(" << fg->ToString() << ":" << node->ToString() << ")";
240     }
241   } else if (op->isa<ValueNode>()) {
242     gsub->buffer << GetValueNode(op)->ToString();
243   } else {
244     gsub->buffer << op->ToString();
245   }
246 }
247 
DumpOperands(const AnfNodePtr & nd,OrderedMap<AnfNodePtr,int32_t> * para_map,const std::shared_ptr<SubGraphIRInfo> & gsub)248 void DumpOperands(const AnfNodePtr &nd, OrderedMap<AnfNodePtr, int32_t> *para_map,
249                   const std::shared_ptr<SubGraphIRInfo> &gsub) {
250   if (nd == nullptr || para_map == nullptr || gsub == nullptr) {
251     return;
252   }
253 
254   gsub->buffer << "(";
255   const auto &inputs = GetInputs(nd);
256   size_t len = inputs.size();
257   if (len > 1) {
258     // skip inputs[0] which is Primitive valuenode
259     for (size_t i = 1; i < len; ++i) {
260       AnfNodePtr in = inputs[i];
261       MS_EXCEPTION_IF_NULL(in);
262       if (i != 1) {
263         gsub->buffer << ", ";
264       }
265       if (in->isa<Parameter>()) {
266         if (!(*para_map)[in]) {
267           gsub->buffer << "%para_" << in->ToString();
268         } else {
269           gsub->buffer << "%para" << (*para_map)[in] << "_" << in->ToString();
270         }
271       } else if (in->isa<CNode>()) {
272         if (gsub->local_var_map.find(in) != gsub->local_var_map.end()) {
273           gsub->buffer << "%" << gsub->local_var_map[in];
274         } else {
275           auto node = in->cast<CNodePtr>();
276           auto fg = node->func_graph();
277           gsub->buffer << "$(" << fg->ToString() << ":" << node->ToString() << ")";
278         }
279       } else if (in->isa<ValueNode>() && !IsValueNode<FuncGraph>(in)) {
280         // non Primitive valuenode
281         gsub->buffer << GetValueNode(in)->ToString();
282       } else if (IsValueNode<FuncGraph>(in)) {
283         FuncGraphPtr fg = GetValueNode<FuncGraphPtr>(in);
284         gsub->buffer << "@" << fg->ToString();
285       } else {
286         gsub->buffer << in->ToString();
287       }
288     }
289   }
290   gsub->buffer << ")";
291 }
292 
DumpParallelInfo(const CNodePtr & node,const std::shared_ptr<SubGraphIRInfo> & gsub)293 void DumpParallelInfo(const CNodePtr &node, const std::shared_ptr<SubGraphIRInfo> &gsub) {
294   if ((node == nullptr) || (gsub == nullptr)) {
295     return;
296   }
297 
298   auto operator_info = node->user_data<parallel::OperatorInfo>();
299   if (operator_info == nullptr) {
300     return;
301   }
302 
303   auto strategy = operator_info->strategy();
304   if (strategy == nullptr) {
305     return;
306   }
307 
308   ValuePtr temp = MakeValue(strategy->GetInputDim());
309   gsub->buffer << " { strategy: ";
310   gsub->buffer << temp->ToString();
311   gsub->buffer << " }";
312 }
313 
DumpAttrs(const std::unordered_map<std::string,ValuePtr> & attrs,const std::shared_ptr<SubGraphIRInfo> & gsub,bool check_strategy=false)314 void DumpAttrs(const std::unordered_map<std::string, ValuePtr> &attrs, const std::shared_ptr<SubGraphIRInfo> &gsub,
315                bool check_strategy = false) {
316   int i = 0;
317   for (const auto &attr : attrs) {
318     if (check_strategy && attr.first == PARALLEL_STRATEGY) {
319       continue;  // skip the strategy
320     }
321     if (i++ != 0) {
322       gsub->buffer << ", ";
323     }
324     gsub->buffer << attr.first << ": ";
325     if (attr.second == nullptr) {
326       gsub->buffer << "null";
327     } else {
328       gsub->buffer << attr.second->ToString();
329     }
330   }
331 }
332 
DumpOperateAttrs(const AnfNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)333 void DumpOperateAttrs(const AnfNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
334   if (op == nullptr || gsub == nullptr) {
335     return;
336   }
337 
338   if (IsValueNode<Primitive>(op)) {
339     PrimitivePtr primitive = GetValueNode<PrimitivePtr>(op);
340     if (!primitive->instance_name().empty()) {
341       gsub->buffer << " {";
342       gsub->buffer << "instance name"
343                    << ": ";
344       gsub->buffer << primitive->instance_name();
345       gsub->buffer << "}";
346     }
347     auto attrs = primitive->attrs();
348     if (!attrs.empty()) {
349       gsub->buffer << " primitive_attrs: {";
350       DumpAttrs(attrs, gsub, true);
351       gsub->buffer << "}";
352     }
353   }
354 }
355 
DumpCNodeAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)356 void DumpCNodeAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
357   if (op == nullptr || gsub == nullptr) {
358     return;
359   }
360   if (op->attrs().empty()) {
361     return;
362   }
363 
364   auto attrs = op->attrs();
365   gsub->buffer << " cnode_attrs: {";
366   DumpAttrs(attrs, gsub);
367   gsub->buffer << "}";
368 }
369 
DumpCNodePrimalAttrs(const CNodePtr & op,const std::shared_ptr<SubGraphIRInfo> & gsub)370 void DumpCNodePrimalAttrs(const CNodePtr &op, const std::shared_ptr<SubGraphIRInfo> &gsub) {
371   if (op == nullptr || gsub == nullptr) {
372     return;
373   }
374   if (op->primal_attrs().empty()) {
375     gsub->buffer << std::endl;
376     return;
377   }
378   auto primal_attrs = op->primal_attrs();
379   gsub->buffer << " cnode_primal_attrs: {";
380   DumpAttrs(primal_attrs, gsub);
381   gsub->buffer << "}";
382   gsub->buffer << std::endl;
383 }
384 
DumpShape(const AnfNodePtr & nd,const FuncGraphPtr & sub_graph,const std::shared_ptr<SubGraphIRInfo> & gsub)385 void DumpShape(const AnfNodePtr &nd, const FuncGraphPtr &sub_graph, const std::shared_ptr<SubGraphIRInfo> &gsub) {
386   if (nd == nullptr || sub_graph == nullptr || gsub == nullptr) {
387     return;
388   }
389 
390   if (nd != sub_graph->get_return()) {
391     gsub->buffer << "      : (";
392     PrintNodeInputType(gsub->buffer, nd);
393     gsub->buffer << ") -> (";
394     PrintNodeOutputType(gsub->buffer, nd);
395     gsub->buffer << ")";
396   } else {
397     gsub->buffer << "      : (";
398     PrintNodeInputType(gsub->buffer, nd);
399     gsub->buffer << ")";
400   }
401 
402   gsub->buffer << std::endl;
403 }
404 
DumpCNode(const CNodePtr & nd,const FuncGraphPtr & sub_graph,OrderedMap<AnfNodePtr,int32_t> * const para_map,const std::shared_ptr<SubGraphIRInfo> & gsub,bool dump_full_name=false,LocDumpMode dump_location=kOff)405 void DumpCNode(const CNodePtr &nd, const FuncGraphPtr &sub_graph, OrderedMap<AnfNodePtr, int32_t> *const para_map,
406                const std::shared_ptr<SubGraphIRInfo> &gsub, bool dump_full_name = false,
407                LocDumpMode dump_location = kOff) {
408   if (nd == nullptr || sub_graph == nullptr || para_map == nullptr || gsub == nullptr) {
409     return;
410   }
411 
412   if (nd != sub_graph->get_return()) {
413     gsub->buffer << "  %" << gsub->local_var << "(" << nd->ToString() << ")"
414                  << " = ";
415     gsub->local_var_map[nd] = gsub->local_var++;
416   } else {
417     gsub->buffer << "  ";
418   }
419 
420   if (nd->inputs().empty()) {
421     MS_LOG(EXCEPTION) << "Input of apply node is empty";
422   }
423 
424   // print operator
425   AnfNodePtr op = nd->input(0);
426   DumpOperator(op, gsub);
427 
428   // print operands
429   DumpOperands(nd, para_map, gsub);
430 
431   // print operator attrs
432   DumpOperateAttrs(op, gsub);
433 
434   // print cnode attrs
435   DumpCNodeAttrs(nd, gsub);
436 
437   // print cnode primal attrs
438   DumpCNodePrimalAttrs(nd, gsub);
439 
440   // print parallel info
441   DumpParallelInfo(nd, gsub);
442 
443   // print shape info
444   DumpShape(nd, sub_graph, gsub);
445 
446   // print kernel info
447   DumpKernelInfo(nd, gsub);
448 
449   if (dump_full_name) {
450     gsub->buffer << "      : (" << nd->fullname_with_scope() << ")" << std::endl;
451   }
452   if (dump_location == kTopStack) {
453     if (label_manage::GetGlobalTraceLabelType() == label_manage::TraceLabelType::kWithUniqueId) {
454       gsub->buffer << trace::GetDebugInfo(nd->debug_info(), "      # ", kSourceLineTipDiscard) << "#"
455                    << label_manage::Label(nd->debug_info()) << "\n";
456       auto primal_debug_infos = nd->primal_debug_infos();
457       if (!primal_debug_infos.empty()) {
458         gsub->buffer << "      # Corresponding forward node candidate:\n";
459         for (auto &primal_debug_info : primal_debug_infos) {
460           gsub->buffer << trace::GetDebugInfo(primal_debug_info, "      # ", kSourceLineTipDiscard) << "#"
461                        << label_manage::Label(primal_debug_info) << "\n";
462         }
463       }
464     } else {
465       gsub->buffer << trace::GetDebugInfo(nd->debug_info(), "      # ", kSourceLineTipDiscard) << "\n";
466       auto primal_debug_infos = nd->primal_debug_infos();
467       if (!primal_debug_infos.empty()) {
468         gsub->buffer << "      # Corresponding forward node candidate:\n";
469         for (auto &primal_debug_info : primal_debug_infos) {
470           gsub->buffer << trace::GetDebugInfo(primal_debug_info, "      # ", kSourceLineTipDiscard) << "\n";
471         }
472       }
473     }
474   } else if (dump_location == kWholeStack) {
475     auto traces = mindspore::trace::GetSourceLineList(nd);
476     for (auto &trace : traces) {
477       gsub->buffer << "      # " << trace;
478     }
479   }
480 }
481 
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=false,LocDumpMode dump_location=kOff)482 void DumpIRInSubgraph(const std::vector<AnfNodePtr> &nodes, OrderedMap<AnfNodePtr, int32_t> *para_map,
483                       OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *const sub_graphs, int32_t total_para,
484                       bool dump_full_name = false, LocDumpMode dump_location = kOff) {
485   if (para_map == nullptr || sub_graphs == nullptr) {
486     return;
487   }
488 
489   for (const auto &nd : nodes) {
490     MS_EXCEPTION_IF_NULL(nd);
491     FuncGraphPtr sub_graph = nd->func_graph();
492     if (sub_graph == nullptr) {
493       MS_LOG(DEBUG) << "Node[" << nd->ToString() << "] belongs to no graph!";
494       continue;
495     }
496     std::shared_ptr<SubGraphIRInfo> gsub = (*sub_graphs)[sub_graph];
497     if (gsub == nullptr) {
498       gsub = std::make_shared<SubGraphIRInfo>();
499       gsub->local_var = 0;
500       (*sub_graphs)[sub_graph] = gsub;
501     }
502     std::vector<AnfNodePtr> parameters = sub_graph->parameters();
503     for (size_t idx = 0; idx < parameters.size(); idx++) {
504       MS_EXCEPTION_IF_NULL(parameters[idx]);
505       if ((*para_map).count(parameters[idx]) == 0) {
506         (*para_map)[parameters[idx]] = total_para++;
507       }
508     }
509     if (!nd->isa<Parameter>()) {
510       if (nd->isa<CNode>()) {
511         // print and record output of operator if it is not 'Return'
512         DumpCNode(nd->cast<CNodePtr>(), sub_graph, para_map, gsub, dump_full_name, dump_location);
513       } else {
514         gsub->buffer << "  " << nd->ToString() << std::endl;
515       }
516     }
517   }
518 }
519 
DumpSubgraph(const OrderedMap<FuncGraphPtr,std::shared_ptr<SubGraphIRInfo>> * sub_graphs,const FuncGraphPtr & graph,OrderedMap<AnfNodePtr,int32_t> * para_map,std::ofstream & fout)520 void DumpSubgraph(const OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> *sub_graphs,
521                   const FuncGraphPtr &graph, OrderedMap<AnfNodePtr, int32_t> *para_map, std::ofstream &fout) {
522   if (sub_graphs == nullptr || graph == nullptr) {
523     return;
524   }
525 
526   fout << "#Total subgraph : " << sub_graphs->size() << std::endl;
527   fout << std::endl;
528 
529   for (const auto &sg : *sub_graphs) {
530     fout << "subgraph attr:" << std::endl;
531     MS_EXCEPTION_IF_NULL(sg.first);
532     for (const auto &attr : sg.first->attrs()) {
533       fout << attr.first << " : ";
534       if (attr.second->isa<BoolImm>()) {
535         fout << GetValue<bool>(attr.second);
536       } else if (attr.second->isa<StringImm>()) {
537         fout << (GetValue<std::string>(attr.second));
538       }
539       fout << std::endl;
540     }
541     fout << "subgraph @" << sg.first->ToString() << "(";
542     if (sg.first != graph) {
543       std::vector<AnfNodePtr> parameters = sg.first->parameters();
544       if (parameters.size() == 1) {
545         MS_EXCEPTION_IF_NULL(parameters[0]);
546         fout << "%para" << (*para_map)[parameters[0]] << "_" << parameters[0]->ToString();
547       } else if (parameters.size() > 1) {
548         for (size_t idx = 0; idx < parameters.size() - 1; idx++) {
549           MS_EXCEPTION_IF_NULL(parameters[idx]);
550           fout << "%para" << (*para_map)[parameters[idx]] << "_" << parameters[idx]->ToString();
551           fout << ", ";
552         }
553         MS_EXCEPTION_IF_NULL(parameters[parameters.size() - 1]);
554         fout << "%para" << (*para_map)[parameters[parameters.size() - 1]] << "_"
555              << parameters[parameters.size() - 1]->ToString();
556       }
557     }
558     fout << ") {" << std::endl;
559     MS_EXCEPTION_IF_NULL(sg.second);
560     fout << sg.second->buffer.str();
561     fout << "}" << std::endl;
562     fout << std::endl;
563   }
564 }
565 
GetEnvDumpIrLineLevel(LocDumpMode * dump_location)566 void GetEnvDumpIrLineLevel(LocDumpMode *dump_location) {
567   static std::unordered_map<std::string, enum LocDumpMode> dump_level_map = {
568     {std::to_string(kOff), kOff}, {std::to_string(kTopStack), kTopStack}, {std::to_string(kWholeStack), kWholeStack}};
569   static const auto dump_level_in_env = common::GetEnv("ENV_DUMP_IR_LINE_LEVEL");
570   auto it = dump_level_map.find(dump_level_in_env);
571   if (it == dump_level_map.end()) {
572     return;
573   }
574   // Use the env setting instead parameter setting.
575   *dump_location = it->second;
576 }
577 
578 #ifdef ENABLE_DUMP_IR
DumpIR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location,const std::string & target_file)579 void DumpIR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name, LocDumpMode dump_location,
580             const std::string &target_file) {
581   GetEnvDumpIrLineLevel(&dump_location);
582   if (graph == nullptr) {
583     return;
584   }
585   auto path = GetSaveGraphsPathName(Common::AddId(filename, ".ir"));
586   if (!target_file.empty()) {
587     path = target_file;
588   }
589   auto realpath = Common::CreatePrefixPath(path);
590   if (!realpath.has_value()) {
591     MS_LOG(ERROR) << "Get real path failed, path=" << path;
592     return;
593   }
594 
595   ChangeFileMode(realpath.value(), S_IWUSR);
596   std::ofstream fout(realpath.value());
597   std::ostringstream buffer;
598   if (!fout.is_open()) {
599     MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
600     return;
601   }
602 
603   auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
604   OrderedMap<AnfNodePtr, int32_t> para_map;
605   // dump global info
606   DumpGlobalInfoEntry(graph, buffer);
607   int32_t total_para = DumpParams(graph, buffer, &para_map);
608 
609   OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
610   // dump ir in each sub graph
611   DumpIRInSubgraph(nodes, &para_map, &sub_graphs, total_para, dump_full_name, dump_location);
612 
613   // output global info
614   fout << buffer.str() << std::endl;
615 
616   // output each sub graph
617   DumpSubgraph(&sub_graphs, graph, &para_map, fout);
618 
619   fout.close();
620   // set file mode to read only by user
621   ChangeFileMode(realpath.value(), S_IRUSR);
622 }
623 
DumpIRForRDR(const std::string & filename,const FuncGraphPtr & graph,bool dump_full_name,LocDumpMode dump_location)624 void DumpIRForRDR(const std::string &filename, const FuncGraphPtr &graph, bool dump_full_name,
625                   LocDumpMode dump_location) {
626   GetEnvDumpIrLineLevel(&dump_location);
627   if (graph == nullptr) {
628     return;
629   }
630   auto path = Common::AddId(filename, ".ir");
631   auto realpath = Common::CreatePrefixPath(path);
632   if (!realpath.has_value()) {
633     MS_LOG(ERROR) << "Get real path failed. path=" << path;
634     return;
635   }
636 
637   ChangeFileMode(realpath.value(), S_IWUSR);
638   std::ofstream fout(realpath.value());
639   std::ostringstream buffer;
640   if (!fout.is_open()) {
641     MS_LOG(ERROR) << "Open dump file '" << realpath.value() << "' failed!" << ErrnoToString(errno);
642     return;
643   }
644 
645   auto nodes = TopoSort(graph->get_return(), SuccDeeperSimple, AlwaysInclude);
646   OrderedMap<AnfNodePtr, int32_t> para_map;
647   // dump global info
648   DumpGlobalInfoEntry(graph, buffer);
649   int32_t total_para = DumpParams(graph, buffer, &para_map);
650 
651   OrderedMap<FuncGraphPtr, std::shared_ptr<SubGraphIRInfo>> sub_graphs;
652   // dump ir in each sub graph
653   DumpIRInSubgraph(nodes, &para_map, &sub_graphs, total_para, dump_full_name, dump_location);
654 
655   // output global info
656   fout << buffer.str() << std::endl;
657 
658   // output each sub graph
659   DumpSubgraph(&sub_graphs, graph, &para_map, fout);
660 
661   fout.close();
662   // set file mode to read only by user
663   ChangeFileMode(realpath.value(), S_IRUSR);
664 }
665 
666 #else
DumpIR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode,const std::string &)667 void DumpIR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode, const std::string &) {
668   static bool already_printed = false;
669   if (already_printed) {
670     return;
671   }
672   already_printed = true;
673   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
674                   << "please recompile source to enable it. See help of building script.";
675 }
DumpIRForRDR(const std::string &,const FuncGraphPtr &,bool,LocDumpMode)676 void DumpIRForRDR(const std::string &, const FuncGraphPtr &, bool, LocDumpMode) {
677   static bool already_printed = false;
678   if (already_printed) {
679     return;
680   }
681   already_printed = true;
682   MS_LOG(WARNING) << "The functionality of dumping function graph IR is disabled, "
683                   << "please recompile source to enable it. See help of building script.";
684 }
685 #endif
686 }  // namespace mindspore
687