LCOV - code coverage report
Current view: top level - j_6shHsYoJ/compiler/graph/passes/format_optimize - transop_without_reshape_fusion_pass.cc Coverage Total Hit
Test: CHG Lines: 100.0 % 1 1
Test Date: 2026-08-28 11:31:20
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : #include "graph/passes/format_optimize/transop_without_reshape_fusion_pass.h"
      12              : #include <algorithm>
      13              : #include <memory>
      14              : #include <sstream>
      15              : #include <string>
      16              : #include <atomic>
      17              : 
      18              : #include "common/plugin/ge_make_unique_util.h"
      19              : #include "framework/common/ge_inner_error_codes.h"
      20              : #include "framework/common/framework_types_internal.h"
      21              : #include "common/op/transop_util.h"
      22              : #include "graph/compute_graph.h"
      23              : #include "graph/debug/ge_attr_define.h"
      24              : #include "graph/ge_tensor.h"
      25              : #include "graph/op_desc.h"
      26              : #include "graph/utils/graph_utils.h"
      27              : #include "graph/utils/node_utils.h"
      28              : #include "graph/utils/op_desc_utils.h"
      29              : #include "graph/utils/type_utils.h"
      30              : #include "graph/common/trans_op_creator.h"
      31              : #include "api/gelib/gelib.h"
      32              : 
      33              : namespace {
      34              : const char *const kRemainNode = "node_remain";
      35              : const int32_t kInvalidFusionOpCount = -1;
      36              : const char *const kAttrNameSrcFormat = "src_format";
      37              : const char *const kAttrNameDstFormat = "dst_format";
      38              : }  // namespace
      39              : 
      40              : namespace ge {
      41              : void TransOpWithoutReshapeFusionPass::SetRemainNode(
      42              :     const std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> &nodes_anchor) {
      43              :   auto iter = nodes_anchor.begin();
      44              :   while (iter != nodes_anchor.end()) {
      45              :     auto in_anchor = iter->second;
      46              :     if (in_anchor == nullptr) {
      47              :       return;
      48              :     }
      49              :     auto in_node = in_anchor->GetOwnerNode();
      50              :     ++iter;
      51              :     if (in_node == nullptr) {
      52              :       return;
      53              :     }
      54              :     if (!IsTransOp(in_node)) {
      55              :       continue;
      56              :     }
      57              : 
      58              :     auto op_desc = in_node->GetOpDesc();
      59              :     if (op_desc == nullptr) {
      60              :       continue;
      61              :     }
      62              :     GELOGI("SetRemainNode node is %s", op_desc->GetName().c_str());
      63              :     GE_IF_BOOL_EXEC(!op_desc->SetExtAttr(kRemainNode, true),
      64              :                     REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", kRemainNode,
      65              :                                          op_desc->GetName().c_str(), op_desc->GetType().c_str());
      66              :                     GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", kRemainNode,
      67              :                            op_desc->GetName().c_str(), op_desc->GetType().c_str());
      68              :                     return);
      69              :     auto out_ctrl_anchor = in_node->GetOutControlAnchor();
      70              :     if (out_ctrl_anchor != nullptr) {
      71              :       remain_out_control_anchors_.emplace(out_ctrl_anchor);
      72              :       for (const auto &peer_in_ctrl_anchor : out_ctrl_anchor->GetPeerInControlAnchors()) {
      73              :         remain_in_control_anchors_.emplace(peer_in_ctrl_anchor);
      74              :       }
      75              :     }
      76              :   }
      77              : }
      78              : 
      79              : bool TransOpWithoutReshapeFusionPass::IsFormatContinuous(const OutDataAnchorPtr &out_anchor,
      80              :                                                          const InDataAnchorPtr &in_anchor) const {
      81              :   if ((out_anchor == nullptr) || (in_anchor == nullptr) || (in_anchor->GetOwnerNode() == nullptr) ||
      82              :       (out_anchor->GetOwnerNode() == nullptr)) {
      83              :     return false;
      84              :   }
      85              :   auto in_node = in_anchor->GetOwnerNode();
      86              :   GE_IF_BOOL_EXEC(in_node == nullptr,
      87              :                   REPORT_INNER_ERR_MSG("E19999", "Param in_anchor's owner node is nullptr, check invalid");
      88              :                   GELOGE(INTERNAL_ERROR, "[Check][Param]Param in_anchor's owner node is nullptr"); return false);
      89              :   auto in_op = in_node->GetOpDesc();
      90              :   auto out_owner_node = out_anchor->GetOwnerNode();
      91              :   GE_IF_BOOL_EXEC(out_owner_node == nullptr,
      92              :                   REPORT_INNER_ERR_MSG("E19999", "Param out_anchor's owner node is nullptr, check invalid");
      93              :                   GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor's owner node is nullptr"); return false);
      94              :   auto out_op = out_owner_node->GetOpDesc();
      95              :   GE_IF_BOOL_EXEC(in_op == nullptr,
      96              :                   REPORT_INNER_ERR_MSG("E19999", "Param in_anchor's owner op_desc is nullptr, check invalid");
      97              :                   GELOGE(INTERNAL_ERROR, "[Check][Param] Param in_anchor's owner op_desc is nullptr"); return false);
      98              :   GE_IF_BOOL_EXEC(out_op == nullptr,
      99              :                   REPORT_INNER_ERR_MSG("E19999", "Param out_anchor's owner op_desc is nullptr, check invalid");
     100              :                   GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor's owner op_desc is nullptr"); return false);
     101              :   auto in_op_desc = in_op->GetInputDescPtr(in_anchor->GetIdx());
     102              :   auto out_op_desc = out_op->GetOutputDescPtr(out_anchor->GetIdx());
     103              :   GE_IF_BOOL_EXEC(in_op_desc == nullptr,
     104              :                   REPORT_INNER_ERR_MSG("E19999", "Param in_anchor corresponding tensor is nullptr, check invalid");
     105              :                   GELOGE(INTERNAL_ERROR, "[Check][Param] Param in_anchor corresponding tensor is nullptr");
     106              :                   return false);
     107              :   GE_IF_BOOL_EXEC(out_op_desc == nullptr,
     108              :                   REPORT_INNER_ERR_MSG("E19999", "Param out_anchor corresponding tensor is nullptr, check invalid");
     109              :                   GELOGE(INTERNAL_ERROR, "[Check][Param] Param out_anchor corresponding tensor is nullptr");
     110              :                   return false);
     111              :   if (!ShapeEqualCheck(in_op_desc->GetShape(), out_op_desc->GetShape())) {
     112              :     GELOGD("Node %s(%s) output shape %s, node %s(%s) input shape %s, not continuous.", out_op->GetNamePtr(),
     113              :            out_op->GetTypePtr(), out_op_desc->GetShape().ToString().c_str(), in_op->GetNamePtr(), in_op->GetTypePtr(),
     114              :            in_op_desc->GetShape().ToString().c_str());
     115              :     return false;
     116              :   }
     117              : 
     118              :   if (in_op_desc->GetFormat() != out_op_desc->GetFormat()) {
     119              :     GELOGD("Node %s(%s) output format %s, node %s(%s) input format %s, not continuous.", out_op->GetNamePtr(),
     120              :            out_op->GetTypePtr(), TypeUtils::FormatToSerialString(out_op_desc->GetFormat()).c_str(), in_op->GetNamePtr(),
     121              :            in_op->GetTypePtr(), TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
     122              :     return false;
     123              :   }
     124              : 
     125              :   if (IsTransOp(in_node) && in_op->GetType() != CAST) {
     126              :     if (in_op_desc->GetFormat() == FORMAT_ND) {
     127              :       GELOGD("Node %s(%s) input format %s, not support fusion.", in_op->GetNamePtr(), in_op->GetTypePtr(),
     128              :              TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
     129              :       return false;
     130              :     }
     131              : 
     132              :     if (!FusionFormatSupport(in_op_desc->GetFormat())) {
     133              :       GELOGD("Node %s(%s) input format %s, not support fusion.", in_op->GetNamePtr(), in_op->GetTypePtr(),
     134              :              TypeUtils::FormatToSerialString(in_op_desc->GetFormat()).c_str());
     135              :       return false;
     136              :     }
     137              :   }
     138              : 
     139              :   return true;
     140              : }
     141              : 
     142              : //      AxpyV2 (FP16 -> FP32)
     143              : //        |
     144              : //       CAST (FP16 -> FP32)
     145              : // 修改背景:AxpyV2算子的原始输出dtype是BF16,在OpJudge阶段storage
     146              : // shape被刷成FP32,被该pass认为两个node的输入输出type一致,将cast节点删除
     147              : // FE在重型格式扩散时,由于cast不是aicore算子,无法扩散到AxpyV2节点,在该阶段FE会插入Trans_cast算子和Cast节点刚好对消
     148              : // 如果该pass认为两个node的输入输出type一致,将cast节点删除,FE在重型格式扩散时,会将AxpyV2格式也设置为NZ格式,插入Trans_cast算子时无法和Cast节点对消
     149              : bool TransOpWithoutReshapeFusionPass::IsTransOpDataTypeContinuous(const OutDataAnchorPtr &out_anchor,
     150              :                                                                   const InDataAnchorPtr &in_anchor) const {
     151              :   if ((out_anchor == nullptr) || (in_anchor == nullptr)) {
     152              :     return false;
     153              :   }
     154              :   const auto in_node = in_anchor->GetOwnerNodeBarePtr();
     155              :   if (in_node == nullptr) {
     156              :     return false;
     157              :   }
     158              :   if (!IsTransOp(in_node)) {
     159              :     return true;
     160              :   }
     161              : 
     162              :   const auto out_node = out_anchor->GetOwnerNodeBarePtr();
     163              :   if (out_node == nullptr) {
     164              :     return false;
     165              :   }
     166              :   const auto in_op_desc = in_node->GetOpDesc();
     167              :   if (in_op_desc == nullptr) {
     168              :     return false;
     169              :   }
     170              :   const auto out_op_desc = out_node->GetOpDesc();
     171              :   if (out_op_desc == nullptr) {
     172              :     return false;
     173              :   }
     174              : 
     175              :   // 转换链融合前需要确认数据类型连续性:当前数据边上游输出 dtype 必须等于下游 TransOp 输入 dtype。
     176              :   const auto input_desc = in_op_desc->GetInputDescPtr(in_anchor->GetIdx());
     177              :   const auto output_desc = out_op_desc->GetOutputDescPtr(out_anchor->GetIdx());
     178              :   if ((input_desc == nullptr) || (output_desc == nullptr)) {
     179              :     return false;
     180              :   }
     181              :   if (input_desc->GetDataType() == output_desc->GetDataType()) {
     182              :     return true;
     183              :   }
     184              : 
     185              :   GELOGD(
     186              :       "[Check][DataType] Trans op fusion is skipped, node:%s(%s), input idx:%d, input datatype:%s, "
     187              :       "prev node:%s(%s), output idx:%d, output datatype:%s.",
     188              :       in_op_desc->GetNamePtr(), in_op_desc->GetTypePtr(), in_anchor->GetIdx(),
     189              :       TypeUtils::DataTypeToSerialString(input_desc->GetDataType()).c_str(), out_op_desc->GetNamePtr(),
     190              :       out_op_desc->GetTypePtr(), out_anchor->GetIdx(),
     191              :       TypeUtils::DataTypeToSerialString(output_desc->GetDataType()).c_str());
     192              :   return false;
     193              : }
     194              : 
     195              : bool TransOpWithoutReshapeFusionPass::HasPrecisionLoss(const OutDataAnchorPtr &out_anchor,
     196              :                                                        const InDataAnchorPtr &in_anchor) const {
     197              :   auto out_node = out_anchor->GetOwnerNode();
     198              :   GE_ASSERT_NOTNULL(out_node);
     199              :   auto in_node = in_anchor->GetOwnerNode();
     200              :   GE_ASSERT_NOTNULL(in_node);
     201              :   if (in_node->GetType() == CAST && TransOpUtil::IsPrecisionLoss(in_node)) {
     202              :     return true;
     203              :   }
     204              :   if (out_node->GetType() == CAST && TransOpUtil::IsPrecisionLoss(out_node)) {
     205              :     return true;
     206              :   }
     207              :   return false;
     208              : }
     209              : 
     210              : graphStatus TransOpWithoutReshapeFusionPass::IsTransposeNoNeedFusion(const Node *node, bool &no_need_fusion) const {
     211              :   no_need_fusion = false;
     212              :   if ((node->GetType() != TRANSPOSE) && (node->GetType() != TRANSPOSED)) {
     213              :     return GRAPH_SUCCESS;
     214              :   }
     215              : 
     216              :   GE_CHECK_NOTNULL(node->GetOpDesc());
     217              :   GE_ASSERT_NOTNULL(node->GetOpDesc()->GetInputDescPtr(0));
     218              :   auto input_format = node->GetOpDesc()->GetInputDescPtr(0)->GetFormat();
     219              :   GE_ASSERT_NOTNULL(node->GetOpDesc()->GetOutputDescPtr(0));
     220              :   auto output_format = node->GetOpDesc()->GetOutputDescPtr(0)->GetFormat();
     221              :   bool is_unknown = false;
     222              :   // No need to fusion when input and output format is same or is unknown shape
     223              :   if ((input_format == output_format) ||
     224              :       ((NodeUtils::GetNodeUnknownShapeStatus(*node, is_unknown) == GRAPH_SUCCESS) && is_unknown)) {
     225              :     GELOGD("Abandoned Fusion node %s(%s) is unknown shape.", node->GetNamePtr(), node->GetTypePtr());
     226              :     no_need_fusion = true;
     227              :   }
     228              :   return GRAPH_SUCCESS;
     229              : }
     230              : 
     231              : graphStatus TransOpWithoutReshapeFusionPass::NeedRemainNode(const OutDataAnchorPtr &out_anchor,
     232              :                                                             const InDataAnchorPtr &in_anchor, bool &need_remain) const {
     233              :   need_remain = false;
     234              :   GE_CHECK_NOTNULL(in_anchor);
     235              :   auto in_node = in_anchor->GetOwnerNodeBarePtr();
     236              :   GE_CHECK_NOTNULL(in_node);
     237              :   if (in_node->GetType() == RESHAPE) {
     238              :     GELOGD("Abandoned Fusion node %s type: RESHAPE", in_node->GetNamePtr());
     239              :     need_remain = true;
     240              :     return GRAPH_SUCCESS;
     241              :   }
     242              : 
     243              :   GE_CHK_STATUS_RET(IsTransposeNoNeedFusion(in_node, need_remain));
     244              :   if (need_remain) {
     245              :     return GRAPH_SUCCESS;
     246              :   }
     247              : 
     248              :   GE_CHECK_NOTNULL(out_anchor);
     249              :   auto out_node = out_anchor->GetOwnerNodeBarePtr();
     250              :   GE_CHECK_NOTNULL(out_node);
     251              :   if (!IsFormatContinuous(out_anchor, in_anchor)) {
     252              :     GELOGD("Abandoned Fusion node %s(%s) and node %s(%s) format is uncontinuous or not support.",
     253              :            out_node->GetNamePtr(), out_node->GetTypePtr(), in_node->GetNamePtr(), in_node->GetTypePtr());
     254              :     need_remain = true;
     255              :     return GRAPH_SUCCESS;
     256              :   }
     257              : 
     258              :   if (!IsTransOpDataTypeContinuous(out_anchor, in_anchor)) {
     259              :     GELOGD("Abandoned Fusion node %s(%s) input datatype is uncontinuous.", in_node->GetNamePtr(),
     260              :            in_node->GetTypePtr());
     261              :     need_remain = true;
     262              :     return GRAPH_SUCCESS;
     263              :   }
     264              : 
     265              :   if (HasPrecisionLoss(out_anchor, in_anchor)) {
     266              :     GELOGD("Abandoned Fusion node %s(%s) and node %s(%s) has precision loss.", out_node->GetNamePtr(),
     267              :            out_node->GetTypePtr(), in_node->GetNamePtr(), in_node->GetTypePtr());
     268              :     need_remain = true;
     269              :   }
     270              :   return GRAPH_SUCCESS;
     271              : }
     272              : 
     273              : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphNodesInfo(const size_t index, bool &has_remain_node,
     274              :                                                                   int32_t &transop_num_count,
     275              :                                                                   std::vector<NodePtr> &sub_graph_nodes) const {
     276              :   has_remain_node = false;
     277              :   transop_num_count = 0;
     278              :   auto nodes_anchor = sub_graph_anchors_[index];
     279              :   auto iter = nodes_anchor.begin();
     280              :   auto first_out_anchor = iter->first;
     281              :   if (first_out_anchor == nullptr) {
     282              :     return GRAPH_SUCCESS;
     283              :   }
     284              :   sub_graph_nodes.push_back(first_out_anchor->GetOwnerNode());
     285              : 
     286              :   while (iter != nodes_anchor.end()) {
     287              :     auto in_anchor = iter->second;
     288              :     bool need_remain = false;
     289              :     GE_CHK_STATUS_RET(NeedRemainNode(iter->first, in_anchor, need_remain));
     290              :     if (need_remain) {
     291              :       has_remain_node = true;
     292              :       break;
     293              :     }
     294              : 
     295              :     auto in_node = in_anchor->GetOwnerNode();
     296              :     GE_CHECK_NOTNULL(in_node);
     297              :     sub_graph_nodes.push_back(in_node);
     298              :     if (IsTransOp(in_node)) {
     299              :       ++transop_num_count;
     300              :     }
     301              :     ++iter;
     302              :   }
     303              :   return GRAPH_SUCCESS;
     304              : }
     305              : 
     306              : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphNodesInfo() {
     307              :   std::vector<bool> sub_graph_has_reshape_node(sub_graph_anchors_.size(), false);
     308              :   std::vector<int32_t> transop_num_count(sub_graph_anchors_.size(), 0);
     309              :   std::vector<std::vector<NodePtr>> sub_graph_nodes(sub_graph_anchors_.size());
     310              :   for (size_t i = 0; i < sub_graph_anchors_.size(); ++i) {
     311              :     bool has_remain_node = false;
     312              :     int32_t current_transop_num_count = 0;
     313              :     std::vector<NodePtr> nodes_tmp;
     314              :     GE_CHK_STATUS_RET(GetSubGraphNodesInfo(i, has_remain_node, current_transop_num_count, nodes_tmp));
     315              :     sub_graph_has_reshape_node[i] = has_remain_node;
     316              :     transop_num_count[i] = current_transop_num_count;
     317              :     sub_graph_nodes[i].swap(nodes_tmp);
     318              :     if (sub_graph_has_reshape_node[i]) {
     319              :       SetRemainNode(sub_graph_anchors_[i]);
     320              :     }
     321              :   }
     322              : 
     323              :   sub_graph_has_reshape_node_.swap(sub_graph_has_reshape_node);
     324              :   transop_num_count_.swap(transop_num_count);
     325              :   sub_graph_nodes_.swap(sub_graph_nodes);
     326              :   return GRAPH_SUCCESS;
     327              : }
     328              : 
     329              : void TransOpWithoutReshapeFusionPass::GetOutDataPeerInControlAnchors(
     330              :     const size_t index, std::vector<std::vector<InControlAnchorPtr>> &out_data_peer_in_control_anchors) {
     331              :   // The caller guarantees that the index is legal.
     332              :   for (size_t j = 1; j < sub_graph_anchors_[index].size(); ++j) {
     333              :     auto nodes_anchor = sub_graph_anchors_[index][j];
     334              :     auto out_data_anchor = nodes_anchor.first;
     335              :     GE_CHECK_NOTNULL_JUST_RETURN(out_data_anchor);
     336              :     for (const auto &peer_in_control_anchor : out_data_anchor->GetPeerInControlAnchors()) {
     337              :       GE_CHECK_NOTNULL_JUST_RETURN(peer_in_control_anchor);
     338              :       auto peer_node = peer_in_control_anchor->GetOwnerNode();
     339              :       if (peer_node == nullptr) {
     340              :         continue;
     341              :       }
     342              :       auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
     343              :       if (iter == sub_graph_nodes_[index].end()) {
     344              :         out_data_peer_in_control_anchors[index].push_back(peer_in_control_anchor);
     345              :       } else {
     346              :         sub_graph_has_out_data_peer_in_control_edge_[index] = true;
     347              :       }
     348              :     }
     349              :   }
     350              : }
     351              : 
     352              : void TransOpWithoutReshapeFusionPass::GetInControlPeerOutControlAnchors(
     353              :     const size_t index, std::vector<std::vector<OutControlAnchorPtr>> &in_control_peer_out_control_anchors) {
     354              :   // The caller guarantees that the index is legal.
     355              :   for (size_t j = 1; j < (sub_graph_nodes_[index].size() - 1); ++j) {
     356              :     auto node = sub_graph_nodes_[index][j];
     357              :     GE_CHECK_NOTNULL_JUST_RETURN(node);
     358              :     auto in_control_anchor = node->GetInControlAnchor();
     359              :     if (in_control_anchor == nullptr) {
     360              :       continue;
     361              :     }
     362              : 
     363              :     for (const auto &peer_out_anchor : in_control_anchor->GetPeerOutControlAnchors()) {
     364              :       GE_CHECK_NOTNULL_JUST_RETURN(peer_out_anchor);
     365              :       auto peer_node = peer_out_anchor->GetOwnerNode();
     366              :       if (peer_node == nullptr) {
     367              :         continue;
     368              :       }
     369              :       auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
     370              :       if (iter == sub_graph_nodes_[index].end()) {
     371              :         in_control_peer_out_control_anchors[index].push_back(peer_out_anchor);
     372              :       } else {
     373              :         sub_graph_has_control_edge_[index] = true;
     374              :       }
     375              :     }
     376              :   }
     377              : }
     378              : 
     379              : void TransOpWithoutReshapeFusionPass::GetOutControlPeerAnchors(
     380              :     const size_t index, std::vector<std::vector<InControlAnchorPtr>> &out_control_peer_in_control_anchors,
     381              :     std::vector<std::vector<InDataAnchorPtr>> &out_control_peer_in_data_anchors) {
     382              :   for (size_t j = 0; j < sub_graph_nodes_[index].size() - 1; ++j) {
     383              :     auto node = sub_graph_nodes_[index][j];
     384              :     GE_CHECK_NOTNULL_JUST_RETURN(node);
     385              :     auto out_control_anchor = node->GetOutControlAnchor();
     386              :     GE_CHECK_NOTNULL_JUST_RETURN(out_control_anchor);
     387              : 
     388              :     for (const auto &peer_in_anchor : out_control_anchor->GetPeerInControlAnchors()) {
     389              :       GE_CHECK_NOTNULL_JUST_RETURN(peer_in_anchor);
     390              :       auto peer_node = peer_in_anchor->GetOwnerNode();
     391              :       if (peer_node == nullptr) {
     392              :         continue;
     393              :       }
     394              :       auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
     395              :       if (iter == sub_graph_nodes_[index].end()) {
     396              :         /*
     397              :           opA
     398              :            |
     399              :          trans1 ---->opD
     400              :            |          |
     401              :          trans2<-----opE
     402              :          临时方案:A-B-C-D若此链路上A所有控制输出节点,都被融合后链路的尾部算子控制,有控制边下移成环的风险。
     403              :          转换算子一般为框架成图后插入,且insertbefore的场景的输出控制才重要。
     404              :          因此认为链路头部的输出控制不重要,为避免成环,不处理头部转换算子的控制边
     405              :          正式方案:控制边链接时需要遍历图,判断有成环风险后放弃融合。
     406              :           */
     407              :         if (j > 1U) {
     408              :           out_control_peer_in_control_anchors[index].push_back(peer_in_anchor);
     409              :         }
     410              :       } else {
     411              :         sub_graph_has_control_edge_[index] = true;
     412              :       }
     413              :     }
     414              : 
     415              :     for (const auto &peer_in_anchor : out_control_anchor->GetPeerInDataAnchors()) {
     416              :       GE_CHECK_NOTNULL_JUST_RETURN(peer_in_anchor);
     417              :       auto peer_node = peer_in_anchor->GetOwnerNode();
     418              :       if (peer_node == nullptr) {
     419              :         continue;
     420              :       }
     421              :       auto iter = std::find(sub_graph_nodes_[index].begin(), sub_graph_nodes_[index].end(), peer_node);
     422              :       if (iter == sub_graph_nodes_[index].end()) {
     423              :         if (j > 0) {
     424              :           out_control_peer_in_data_anchors[index].push_back(peer_in_anchor);
     425              :         }
     426              :       } else {
     427              :         sub_graph_has_control_edge_[index] = true;
     428              :       }
     429              :     }
     430              :   }
     431              : }
     432              : 
     433              : void TransOpWithoutReshapeFusionPass::GetControlAnchors() {
     434              :   std::vector<std::vector<OutControlAnchorPtr>> in_control_peer_out_control_anchors(sub_graph_nodes_.size());
     435              :   std::vector<std::vector<InControlAnchorPtr>> out_control_peer_in_control_anchors(sub_graph_nodes_.size());
     436              :   std::vector<std::vector<InDataAnchorPtr>> out_control_peer_in_data_anchors(sub_graph_nodes_.size());
     437              :   std::vector<std::vector<InControlAnchorPtr>> out_data_peer_in_control_anchors(sub_graph_nodes_.size());
     438              :   std::vector<bool> sub_graph_has_control_edge(sub_graph_nodes_.size(), false);
     439              :   sub_graph_has_control_edge_.swap(sub_graph_has_control_edge);
     440              :   std::vector<bool> sub_graph_has_out_data_peer_in_control_edge(sub_graph_nodes_.size(), false);
     441              :   sub_graph_has_out_data_peer_in_control_edge_.swap(sub_graph_has_out_data_peer_in_control_edge);
     442              :   for (size_t i = 0; i < sub_graph_nodes_.size(); ++i) {
     443              :     if (sub_graph_has_reshape_node_[i]) {
     444              :       continue;
     445              :     }
     446              : 
     447              :     GetOutDataPeerInControlAnchors(i, out_data_peer_in_control_anchors);
     448              : 
     449              :     GetInControlPeerOutControlAnchors(i, in_control_peer_out_control_anchors);
     450              : 
     451              :     GetOutControlPeerAnchors(i, out_control_peer_in_control_anchors, out_control_peer_in_data_anchors);
     452              :   }
     453              : 
     454              :   in_control_peer_out_control_anchors_.swap(in_control_peer_out_control_anchors);
     455              :   out_control_peer_in_control_anchors_.swap(out_control_peer_in_control_anchors);
     456              :   out_control_peer_in_data_anchors_.swap(out_control_peer_in_data_anchors);
     457              :   out_data_peer_in_control_anchors_.swap(out_data_peer_in_control_anchors);
     458              : }
     459              : 
     460              : void TransOpWithoutReshapeFusionPass::EraseInvalidAnchorsPair() {
     461              :   auto sub_graph_iter = sub_graph_anchors_.begin();
     462              :   while (sub_graph_iter != sub_graph_anchors_.end()) {
     463              :     if (sub_graph_iter->size() <= 1) {
     464              :       sub_graph_iter = sub_graph_anchors_.erase(sub_graph_iter);
     465              :     } else {
     466              :       ++sub_graph_iter;
     467              :     }
     468              :   }
     469              : }
     470              : 
     471              : void TransOpWithoutReshapeFusionPass::UpdateOutputName(const OutDataAnchorPtr &out_anchor,
     472              :                                                        const InDataAnchorPtr &old_peer_in_anchor,
     473              :                                                        const NodePtr &in_owner_node) const {
     474              :   if ((out_anchor == nullptr) || (old_peer_in_anchor == nullptr) || (in_owner_node == nullptr)) {
     475              :     GELOGI("out_anchor or old_peer_in_anchor or in_owner_node is nullptr");
     476              :     return;
     477              :   }
     478              :   auto out_owner_node = out_anchor->GetOwnerNode();
     479              :   GE_CHECK_NOTNULL_JUST_RETURN(out_owner_node);
     480              :   GE_CHECK_NOTNULL_JUST_RETURN(old_peer_in_anchor->GetOwnerNode());
     481              :   auto old_peer_in_name = old_peer_in_anchor->GetOwnerNode()->GetName();
     482              :   auto output_op = out_owner_node->GetOpDesc();
     483              :   GE_CHECK_NOTNULL_JUST_RETURN(output_op);
     484              :   auto output_names = output_op->GetAllOutputName();
     485              :   const auto old_peer_in_name_iter = output_names.find(old_peer_in_name);
     486              :   if (old_peer_in_name_iter != output_names.end()) {
     487              :     output_names.erase(old_peer_in_name_iter);
     488              :   }
     489              :   output_names[in_owner_node->GetName()] = out_anchor->GetIdx();
     490              :   if (!output_op->UpdateOutputName(output_names)) {
     491              :     GELOGW("output_op UpdateOutputName failed");
     492              :   }
     493              : }
     494              : 
     495              : void TransOpWithoutReshapeFusionPass::UpdateInputName(const OutDataAnchorPtr &old_peer_out_anchor,
     496              :                                                       const InDataAnchorPtr &in_anchor,
     497              :                                                       const NodePtr &out_owner_node) const {
     498              :   if ((old_peer_out_anchor == nullptr) || (in_anchor == nullptr) || (out_owner_node == nullptr)) {
     499              :     GELOGI("old_peer_out_anchor or in_anchor or out_owner_node is nullptr");
     500              :     return;
     501              :   }
     502              :   auto old_node = old_peer_out_anchor->GetOwnerNode();
     503              :   GE_CHECK_NOTNULL_JUST_RETURN(old_node);
     504              :   auto old_peer_out_name = old_node->GetName();
     505              :   auto in_owner_node = in_anchor->GetOwnerNode();
     506              :   GE_CHECK_NOTNULL_JUST_RETURN(in_owner_node);
     507              :   auto input_op = in_owner_node->GetOpDesc();
     508              :   GE_CHECK_NOTNULL_JUST_RETURN(input_op);
     509              :   auto input_names = input_op->GetAllInputName();
     510              :   const auto old_peer_out_name_iter = input_names.find(old_peer_out_name);
     511              :   if (old_peer_out_name_iter != input_names.end()) {
     512              :     input_names.erase(old_peer_out_name_iter);
     513              :   }
     514              :   input_names[out_owner_node->GetName()] = in_anchor->GetIdx();
     515              :   input_op->UpdateInputName(input_names);
     516              : }
     517              : 
     518              : graphStatus TransOpWithoutReshapeFusionPass::RelinkSubGraphControlEdges(
     519              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
     520              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
     521              :   auto out_anchor = begin_anchors_pair.first;
     522              :   GE_CHECK_NOTNULL(out_anchor);
     523              :   auto out_owner_node = out_anchor->GetOwnerNode();
     524              :   GE_CHECK_NOTNULL(out_owner_node);
     525              :   auto in_anchor = end_anchors_pair.second;
     526              :   GE_CHECK_NOTNULL(in_anchor);
     527              :   auto in_owner_node = in_anchor->GetOwnerNode();
     528              :   GE_CHECK_NOTNULL(in_owner_node);
     529              :   if (sub_graph_has_control_edge_[index]) {
     530              :     GELOGI("add control edge.src:%s, dst:%s", out_owner_node->GetName().c_str(), in_owner_node->GetName().c_str());
     531              :     if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), in_owner_node->GetInControlAnchor()) !=
     532              :         GRAPH_SUCCESS) {
     533              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     534              :                            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     535              :                            in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
     536              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     537              :              out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), in_owner_node->GetName().c_str(),
     538              :              in_owner_node->GetType().c_str());
     539              :       return GRAPH_FAILED;
     540              :     }
     541              :   }
     542              : 
     543              :   if (sub_graph_has_out_data_peer_in_control_edge_[index]) {
     544              :     GELOGI("add out data 2 in control edge.src:%s, dst:%s", out_owner_node->GetName().c_str(),
     545              :            in_owner_node->GetName().c_str());
     546              :     if (GraphUtils::AddEdge(out_anchor, in_owner_node->GetInControlAnchor()) != GRAPH_SUCCESS) {
     547              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     548              :                            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     549              :                            in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
     550              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     551              :              out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), in_owner_node->GetName().c_str(),
     552              :              in_owner_node->GetType().c_str());
     553              :       return GRAPH_FAILED;
     554              :     }
     555              :   }
     556              :   return GRAPH_SUCCESS;
     557              : }
     558              : 
     559              : graphStatus TransOpWithoutReshapeFusionPass::RelinkControlEdgesWhenDescNotChanged(
     560              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
     561              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
     562              :   if (RelinkSubGraphControlEdges(begin_anchors_pair, end_anchors_pair, index) != GRAPH_SUCCESS) {
     563              :     return GRAPH_FAILED;
     564              :   }
     565              : 
     566              :   auto out_anchor = begin_anchors_pair.first;
     567              :   GE_CHECK_NOTNULL(out_anchor);
     568              :   auto out_owner_node = out_anchor->GetOwnerNode();
     569              :   GE_CHECK_NOTNULL(out_owner_node);
     570              :   auto in_anchor = end_anchors_pair.second;
     571              :   GE_CHECK_NOTNULL(in_anchor);
     572              :   auto in_owner_node = in_anchor->GetOwnerNode();
     573              :   GE_CHECK_NOTNULL(in_owner_node);
     574              :   // cannot remove old control edge
     575              :   for (const auto &peer_in_anchor : out_control_peer_in_control_anchors_[index]) {
     576              :     GE_CHECK_NOTNULL(peer_in_anchor);
     577              :     if (remain_in_control_anchors_.count(peer_in_anchor) > 0) {
     578              :       continue;
     579              :     }
     580              :     GELOGI("add control edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
     581              :            peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
     582              :     if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
     583              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     584              :                            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     585              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
     586              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str());
     587              :       GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     588              :              out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     589              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
     590              :       return GRAPH_FAILED;
     591              :     }
     592              :   }
     593              : 
     594              :   for (const auto &peer_out_anchor : in_control_peer_out_control_anchors_[index]) {
     595              :     GE_CHECK_NOTNULL(peer_out_anchor);
     596              :     if (remain_out_control_anchors_.count(peer_out_anchor) > 0) {
     597              :       continue;
     598              :     }
     599              :     GELOGI("add control edge.src:%s, src idx:%d, dst:%s", peer_out_anchor->GetOwnerNode()->GetName().c_str(),
     600              :            peer_out_anchor->GetIdx(), in_owner_node->GetName().c_str());
     601              :     if (GraphUtils::AddEdge(peer_out_anchor, in_owner_node->GetInControlAnchor()) != GRAPH_SUCCESS) {
     602              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     603              :                            peer_out_anchor->GetOwnerNode()->GetName().c_str(),
     604              :                            peer_out_anchor->GetOwnerNode()->GetType().c_str(), in_owner_node->GetName().c_str(),
     605              :                            in_owner_node->GetType().c_str());
     606              :       GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     607              :              peer_out_anchor->GetOwnerNode()->GetName().c_str(), peer_out_anchor->GetOwnerNode()->GetType().c_str(),
     608              :              in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str());
     609              :       return GRAPH_FAILED;
     610              :     }
     611              :   }
     612              : 
     613              :   for (const auto &peer_in_anchor : out_control_peer_in_data_anchors_[index]) {
     614              :     GE_CHECK_NOTNULL(peer_in_anchor);
     615              :     GELOGI("add out control 2 in data edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
     616              :            peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
     617              :     if (GraphUtils::AddEdge(out_owner_node->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
     618              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     619              :                            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     620              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
     621              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str());
     622              :       GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     623              :              out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     624              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
     625              :       return GRAPH_FAILED;
     626              :     }
     627              :   }
     628              : 
     629              :   for (const auto &peer_in_anchor : out_data_peer_in_control_anchors_[index]) {
     630              :     GE_CHECK_NOTNULL(peer_in_anchor);
     631              :     GELOGI("add out data 2 in control edge.src:%s, dst:%s, dst idx:%d", out_owner_node->GetName().c_str(),
     632              :            peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetIdx());
     633              :     if (GraphUtils::AddEdge(out_anchor, peer_in_anchor) != GRAPH_SUCCESS) {
     634              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
     635              :                            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     636              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
     637              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str());
     638              :       GELOGE(GRAPH_FAILED, "[Add]ControlEdge] between op:%s(%s) and op:%s(%s) failed",
     639              :              out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(),
     640              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
     641              :       return GRAPH_FAILED;
     642              :     }
     643              :   }
     644              :   return GRAPH_SUCCESS;
     645              : }
     646              : 
     647              : graphStatus TransOpWithoutReshapeFusionPass::RelinkNodesWhenDescNotChanged(
     648              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &begin_anchors_pair,
     649              :     const std::pair<OutDataAnchorPtr, InDataAnchorPtr> &end_anchors_pair, const int32_t index) {
     650              :   auto out_anchor = begin_anchors_pair.first;
     651              :   GE_CHECK_NOTNULL(out_anchor);
     652              :   auto out_owner_node = out_anchor->GetOwnerNode();
     653              :   GE_CHECK_NOTNULL(out_owner_node);
     654              :   auto in_anchor = end_anchors_pair.second;
     655              :   GE_CHECK_NOTNULL(in_anchor);
     656              :   auto in_owner_node = in_anchor->GetOwnerNode();
     657              :   GE_CHECK_NOTNULL(in_owner_node);
     658              :   GELOGI("remove edge.src %s, src idx:%d, dst:%s, dst idx:%d",
     659              :          end_anchors_pair.first->GetOwnerNode()->GetName().c_str(), end_anchors_pair.first->GetIdx(),
     660              :          in_owner_node->GetName().c_str(), in_anchor->GetIdx());
     661              :   GE_CHK_STATUS_RET(GraphUtils::RemoveEdge(end_anchors_pair.first, in_anchor),
     662              :                     "[Remove][Edge] between %s(%s)(index:%d) and %s(%s)(index:%d) failed",
     663              :                     out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
     664              :                     in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
     665              :   GELOGI("relink node.src node:%s, src idx:%d, dst node:%s, dst idx:%d", out_owner_node->GetName().c_str(),
     666              :          out_anchor->GetIdx(), in_owner_node->GetName().c_str(), in_anchor->GetIdx());
     667              :   if (GraphUtils::AddEdge(out_anchor, in_anchor) != GRAPH_SUCCESS) {
     668              :     REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:%d) and op:%s(%s)(index:%d) failed",
     669              :                          out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
     670              :                          in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
     671              :     GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:%d) and op:%s(%s)(index:%d) failed",
     672              :            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
     673              :            in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
     674              :     return GRAPH_FAILED;
     675              :   } else {
     676              :     auto old_peer_in_anchor = begin_anchors_pair.second;
     677              :     UpdateOutputName(out_anchor, old_peer_in_anchor, in_owner_node);
     678              : 
     679              :     auto old_peer_out_anchor = end_anchors_pair.first;
     680              :     UpdateInputName(old_peer_out_anchor, in_anchor, out_owner_node);
     681              :   }
     682              : 
     683              :   return RelinkControlEdgesWhenDescNotChanged(begin_anchors_pair, end_anchors_pair, index);
     684              : }
     685              : 
     686              : OpDescPtr TransOpWithoutReshapeFusionPass::GetFormatTransferOp(const GeTensorDesc &format_trans_input_desc,
     687              :                                                                const GeTensorDesc &format_trans_output_desc) const {
     688              :   static std::atomic_long atomic_fusion_format_transfer_op_count(1);
     689              :   auto fusion_format_transfer_op_count = atomic_fusion_format_transfer_op_count.fetch_add(1);
     690              : 
     691              :   std::stringstream format_transfer_op_name;
     692              :   format_transfer_op_name << "fusion_format_transfer_" << fusion_format_transfer_op_count;
     693              :   OpDescPtr format_transfer_op = TransOpCreator::CreateTransDataOp(format_transfer_op_name.str(),
     694              :                                                                    format_trans_input_desc, format_trans_output_desc);
     695              :   if (format_transfer_op == nullptr) {
     696              :     GELOGW("[New][OpDesc] transdata failed");
     697              :     return nullptr;
     698              :   }
     699              : 
     700              :   GE_IF_BOOL_EXEC(!AttrUtils::SetInt(format_transfer_op, ATTR_NAME_INPUT_FORMAT,
     701              :                                      static_cast<int64_t>(format_trans_input_desc.GetFormat())),
     702              :                   REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_INPUT_FORMAT.c_str(),
     703              :                                        format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
     704              :                   GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_INPUT_FORMAT.c_str(),
     705              :                          format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
     706              :                   return nullptr);
     707              :   GE_IF_BOOL_EXEC(!AttrUtils::SetInt(format_transfer_op, ATTR_NAME_OUTPUT_FORMAT,
     708              :                                      static_cast<int64_t>(format_trans_output_desc.GetFormat())),
     709              :                   REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", ATTR_NAME_OUTPUT_FORMAT.c_str(),
     710              :                                        format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
     711              :                   GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", ATTR_NAME_OUTPUT_FORMAT.c_str(),
     712              :                          format_transfer_op->GetName().c_str(), format_transfer_op->GetType().c_str());
     713              :                   return nullptr);
     714              : 
     715              :   return format_transfer_op;
     716              : }
     717              : 
     718              : OpDescPtr TransOpWithoutReshapeFusionPass::GetCastOp(const GeTensorDesc &cast_input_desc,
     719              :                                                      const GeTensorDesc &cast_output_desc) const {
     720              :   static std::atomic_long atomic_fusion_cast_op_count(1);
     721              :   auto fusion_cast_op_count = atomic_fusion_cast_op_count.fetch_add(1);
     722              : 
     723              :   std::stringstream cast_op_name;
     724              :   cast_op_name << "fusion_cast_op_" << fusion_cast_op_count;
     725              :   auto node_op = ge::OperatorFactory::CreateOperator(cast_op_name.str().c_str(), CAST);
     726              :   auto cast_op = ge::OpDescUtils::GetOpDescFromOperator(node_op);
     727              :   node_op.BreakConnect();
     728              :   if (cast_op == nullptr) {
     729              :     REPORT_INNER_ERR_MSG("E19999", "Create operator:%s(%s) failed", cast_op_name.str().c_str(), CAST);
     730              :     GELOGE(INTERNAL_ERROR, "[Create][Operator] %s(%s) failed", cast_op_name.str().c_str(), CAST);
     731              :     return nullptr;
     732              :   }
     733              :   const int32_t default_input_index = 0;
     734              :   const int32_t default_output_index = 0;
     735              :   if (cast_op->GetInputsSize() == 0) {
     736              :     GE_IF_BOOL_EXEC(cast_op->AddInputDesc(cast_input_desc) != GRAPH_SUCCESS,
     737              :                     REPORT_INNER_ERR_MSG("E19999", "Add input desc to op:%s(%s) failed", cast_op->GetName().c_str(),
     738              :                                          cast_op->GetType().c_str());
     739              :                     GELOGE(INTERNAL_ERROR, "[Add][InputDesc] to op:%s(%s) failed", cast_op->GetName().c_str(),
     740              :                            cast_op->GetType().c_str());
     741              :                     return nullptr);
     742              :   } else {
     743              :     GE_IF_BOOL_EXEC(cast_op->UpdateInputDesc(default_input_index, cast_input_desc) != GRAPH_SUCCESS,
     744              :                     REPORT_INNER_ERR_MSG("E19999", "Update input:%d desc of op:%s(%s) failed", default_input_index,
     745              :                                          cast_op->GetName().c_str(), cast_op->GetType().c_str());
     746              :                     GELOGE(INTERNAL_ERROR, "[Update][InputDesc] of op:%s(%s) failed, input index:%d",
     747              :                            cast_op->GetName().c_str(), cast_op->GetType().c_str(), default_input_index);
     748              :                     return nullptr);
     749              :   }
     750              : 
     751              :   if (cast_op->GetOutputsSize() == 0) {
     752              :     GE_IF_BOOL_EXEC(cast_op->AddOutputDesc(cast_output_desc) != GRAPH_SUCCESS,
     753              :                     REPORT_INNER_ERR_MSG("E19999", "Add output desc to op:%s(%s) failed", cast_op->GetName().c_str(),
     754              :                                          cast_op->GetType().c_str());
     755              :                     GELOGE(INTERNAL_ERROR, "[Add][OutputDesc] to op:%s(%s) failed", cast_op->GetName().c_str(),
     756              :                            cast_op->GetType().c_str());
     757              :                     return nullptr);
     758              :   } else {
     759              :     GE_IF_BOOL_EXEC(cast_op->UpdateOutputDesc(default_output_index, cast_output_desc) != GRAPH_SUCCESS,
     760              :                     REPORT_INNER_ERR_MSG("E19999", "Update output:%d desc of op:%s(%s) failed", default_output_index,
     761              :                                          cast_op->GetName().c_str(), cast_op->GetType().c_str());
     762              :                     GELOGE(INTERNAL_ERROR, "[Update][OutputDesc] of op:%s(%s) failed, output index:%d",
     763              :                            cast_op->GetName().c_str(), cast_op->GetType().c_str(), default_output_index);
     764              :                     return nullptr);
     765              :   }
     766              : 
     767              :   if (!AttrUtils::SetInt(cast_op, CAST_ATTR_DST_TYPE, static_cast<int64_t>(cast_output_desc.GetDataType()))) {
     768              :     REPORT_INNER_ERR_MSG("E19999", "Set Attr:%s to op:%s(%s) failed", CAST_ATTR_DST_TYPE.c_str(),
     769              :                          cast_op->GetName().c_str(), cast_op->GetType().c_str());
     770              :     GELOGE(INTERNAL_ERROR, "[Set][Attr] %s to op:%s(%s) failed", CAST_ATTR_DST_TYPE.c_str(), cast_op->GetName().c_str(),
     771              :            cast_op->GetType().c_str());
     772              :     return nullptr;
     773              :   }
     774              :   return cast_op;
     775              : }
     776              : 
     777              : bool TransOpWithoutReshapeFusionPass::InsertCastFirstCheck(const GeTensorDesc &out_desc,
     778              :                                                            const GeTensorDesc &in_desc) const {
     779              :   return (out_desc.GetDataType() != in_desc.GetDataType()) && (out_desc.GetDataType() != DT_FLOAT16) &&
     780              :          (in_desc.GetDataType() == DT_FLOAT16);
     781              : }
     782              : 
     783              : void TransOpWithoutReshapeFusionPass::GetFormatTransferDesc(const GeTensorDesc &out_desc, const GeTensorDesc &in_desc,
     784              :                                                             GeTensorDesc &format_transfer_input,
     785              :                                                             GeTensorDesc &format_transfer_output) const {
     786              :   bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
     787              :   if (insert_cast_first) {
     788              :     format_transfer_input = out_desc;
     789              :     format_transfer_input.SetDataType(in_desc.GetDataType());
     790              :     format_transfer_output = in_desc;
     791              :   } else {
     792              :     format_transfer_input = out_desc;
     793              :     format_transfer_output = in_desc;
     794              :     format_transfer_output.SetDataType(out_desc.GetDataType());
     795              :   }
     796              : }
     797              : 
     798              : void TransOpWithoutReshapeFusionPass::GetCastOpDesc(const GeTensorDesc &out_desc, const GeTensorDesc &in_desc,
     799              :                                                     GeTensorDesc &cast_input, GeTensorDesc &cast_output) const {
     800              :   bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
     801              :   if (insert_cast_first) {
     802              :     cast_input = out_desc;
     803              :     cast_output = out_desc;
     804              :     cast_output.SetDataType(in_desc.GetDataType());
     805              :   } else {
     806              :     cast_input = in_desc;
     807              :     cast_input.SetDataType(out_desc.GetDataType());
     808              :     cast_output = in_desc;
     809              :   }
     810              : }
     811              : 
     812              : void TransOpWithoutReshapeFusionPass::GetBeginOutDescAndEndInDesc(const int32_t index, GeTensorDesc &out_desc,
     813              :                                                                   GeTensorDesc &in_desc) {
     814              :   auto nodes_anchor = sub_graph_anchors_[index];
     815              :   auto out_peer_anchor = nodes_anchor.front().second;
     816              :   GE_CHECK_NOTNULL_JUST_RETURN(out_peer_anchor);
     817              :   auto out_owner_node = out_peer_anchor->GetOwnerNode();
     818              :   GE_CHECK_NOTNULL_JUST_RETURN(out_owner_node);
     819              :   auto out_peer_op_desc = out_owner_node->GetOpDesc();
     820              :   GE_IF_BOOL_EXEC(
     821              :       out_peer_op_desc == nullptr, GELOGE(INTERNAL_ERROR, "[Get][OpDesc] failed, out_peer_op_desc is nullptr"); return);
     822              :   out_desc = out_peer_op_desc->GetInputDesc(out_peer_anchor->GetIdx());
     823              : 
     824              :   auto in_peer_anchor = nodes_anchor.back().first;
     825              :   GE_CHECK_NOTNULL_JUST_RETURN(in_peer_anchor);
     826              :   auto in_owner_node = in_peer_anchor->GetOwnerNode();
     827              :   GE_CHECK_NOTNULL_JUST_RETURN(in_owner_node);
     828              :   auto in_peer_op_desc = in_owner_node->GetOpDesc();
     829              :   GE_IF_BOOL_EXEC(
     830              :       in_peer_op_desc == nullptr, GELOGE(INTERNAL_ERROR, "[Get][OpDesc] failed, in_peer_op_desc is nullptr"); return);
     831              :   in_desc = in_peer_op_desc->GetOutputDesc(in_peer_anchor->GetIdx());
     832              : }
     833              : 
     834              : graphStatus TransOpWithoutReshapeFusionPass::FormatFusion(const int32_t index, OpDescPtr &format_transfer_op,
     835              :                                                           int32_t &fusion_op_count, bool &fusion_continue) {
     836              :   GeTensorDesc out_desc;
     837              :   GeTensorDesc in_desc;
     838              :   GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
     839              : 
     840              :   GeTensorDesc format_transfer_input;
     841              :   GeTensorDesc format_transfer_output;
     842              :   GetFormatTransferDesc(out_desc, in_desc, format_transfer_input, format_transfer_output);
     843              : 
     844              :   if ((out_desc.GetFormat() == in_desc.GetFormat()) &&
     845              :       (!ShapeEqualCheck(out_desc.GetShape(), in_desc.GetShape()) ||
     846              :        !ShapeEqualCheck(out_desc.GetOriginShape(), in_desc.GetOriginShape()))) {
     847              :     SetRemainNode(sub_graph_anchors_[index]);
     848              :     return GRAPH_SUCCESS;
     849              :   }
     850              : 
     851              :   if ((out_desc.GetFormat() != in_desc.GetFormat()) && FusionFormatSupport(out_desc.GetFormat()) &&
     852              :       FusionFormatSupport(in_desc.GetFormat())) {
     853              :     // create format transop
     854              :     format_transfer_op = GetFormatTransferOp(format_transfer_input, format_transfer_output);
     855              :     if (format_transfer_op != nullptr) {
     856              :       ++fusion_op_count;
     857              :       GELOGI("support format transfer op %s", format_transfer_op->GetName().c_str());
     858              :     } else {
     859              :       GELOGW("ability not support.src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
     860              :              format_transfer_input.GetFormat(), format_transfer_input.GetDataType(), format_transfer_output.GetFormat(),
     861              :              format_transfer_output.GetDataType());
     862              :       fusion_op_count = kInvalidFusionOpCount;
     863              :     }
     864              :   } else if (out_desc.GetFormat() != in_desc.GetFormat()) {
     865              :     SetRemainNode(sub_graph_anchors_[index]);
     866              :     return GRAPH_SUCCESS;
     867              :   }
     868              :   fusion_continue = true;
     869              :   return GRAPH_SUCCESS;
     870              : }
     871              : 
     872              : graphStatus TransOpWithoutReshapeFusionPass::DataTypeFusion(const int32_t index, OpDescPtr &cast_op,
     873              :                                                             int32_t &fusion_op_count) {
     874              :   GeTensorDesc out_desc;
     875              :   GeTensorDesc in_desc;
     876              :   GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
     877              : 
     878              :   GeTensorDesc cast_input;
     879              :   GeTensorDesc cast_output;
     880              :   GetCastOpDesc(out_desc, in_desc, cast_input, cast_output);
     881              : 
     882              :   if ((fusion_op_count != kInvalidFusionOpCount) && (out_desc.GetDataType() != in_desc.GetDataType())) {
     883              :     // create cast op
     884              :     cast_op = GetCastOp(cast_input, cast_output);
     885              :     if (cast_op == nullptr) {
     886              :       fusion_op_count = kInvalidFusionOpCount;
     887              :       return GRAPH_FAILED;
     888              :     }
     889              : 
     890              :     bool is_supported = false;
     891              :     (void)TransOpCreator::CheckAccuracySupported(cast_op, is_supported);
     892              :     if (is_supported) {
     893              :       ++fusion_op_count;
     894              :       GELOGI("support cast op %s. src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
     895              :              cast_op->GetName().c_str(), cast_input.GetFormat(), cast_input.GetDataType(), cast_output.GetFormat(),
     896              :              cast_output.GetDataType());
     897              :     } else {
     898              :       GELOGW("ability not support.src format:%d, src datatype:%d, dst format:%d, dst datatype:%d",
     899              :              cast_input.GetFormat(), cast_input.GetDataType(), cast_output.GetFormat(), cast_output.GetDataType());
     900              :       fusion_op_count = kInvalidFusionOpCount;
     901              :     }
     902              :   }
     903              :   return GRAPH_SUCCESS;
     904              : }
     905              : 
     906              : graphStatus TransOpWithoutReshapeFusionPass::TransOpFuseHandle(const ComputeGraphPtr &graph, const int32_t index) {
     907              :   bool fusion_continue = false;
     908              :   OpDescPtr format_transfer_op = nullptr;
     909              :   int32_t fusion_op_count = 0;
     910              :   auto fortmat_fusion_ret = FormatFusion(index, format_transfer_op, fusion_op_count, fusion_continue);
     911              :   if ((fortmat_fusion_ret != GRAPH_SUCCESS) || !fusion_continue) {
     912              :     SetRemainNode(sub_graph_anchors_[index]);
     913              :     return GRAPH_SUCCESS;
     914              :   }
     915              : 
     916              :   OpDescPtr cast_op = nullptr;
     917              :   if (DataTypeFusion(index, cast_op, fusion_op_count) != GRAPH_SUCCESS) {
     918              :     SetRemainNode(sub_graph_anchors_[index]);
     919              :     return GRAPH_SUCCESS;
     920              :   }
     921              : 
     922              :   if ((fusion_op_count > 0) && (fusion_op_count < transop_num_count_[index])) {
     923              :     GeTensorDesc out_desc;
     924              :     GeTensorDesc in_desc;
     925              :     GetBeginOutDescAndEndInDesc(index, out_desc, in_desc);
     926              :     bool insert_cast_first = InsertCastFirstCheck(out_desc, in_desc);
     927              :     if (InsertNewTransOp(graph, cast_op, format_transfer_op, index, insert_cast_first) != GRAPH_SUCCESS) {
     928              :       return GRAPH_FAILED;
     929              :     }
     930              :   } else {
     931              :     // remain all nodes
     932              :     SetRemainNode(sub_graph_anchors_[index]);
     933              :   }
     934              :   return GRAPH_SUCCESS;
     935              : }
     936              : 
     937              : void TransOpWithoutReshapeFusionPass::RemoveNousedNodes(const ComputeGraphPtr &graph) {
     938              :   if (graph == nullptr) {
     939              :     return;
     940              :   }
     941              :   for (size_t i = 0; i < sub_graph_nodes_.size(); ++i) {
     942              :     if (sub_graph_has_reshape_node_[i]) {
     943              :       continue;
     944              :     }
     945              : 
     946              :     for (const auto &node : sub_graph_nodes_[i]) {
     947              :       GE_CHECK_NOTNULL_JUST_RETURN(node);
     948              :       // remove nodes
     949              :       if (!IsTransOp(node)) {
     950              :         continue;
     951              :       }
     952              : 
     953              :       auto op_desc = node->GetOpDesc();
     954              :       GE_CHECK_NOTNULL_JUST_RETURN(op_desc);
     955              :       bool node_remain_flag = op_desc->TryGetExtAttr(kRemainNode, false);
     956              :       if (node_remain_flag) {
     957              :         continue;
     958              :       }
     959              : 
     960              :       GE_IF_BOOL_EXEC(!op_desc->SetExtAttr(kRemainNode, true),
     961              :                       GELOGE(INTERNAL_ERROR, "[Set][ExtAttr] for op:%s failed", op_desc->GetName().c_str());
     962              :                       return);
     963              :       GELOGI("remove node:%s", node->GetName().c_str());
     964              :       if (GraphUtils::IsolateNode(node, {0}) != GRAPH_SUCCESS) {
     965              :         GELOGW("Isolate node: %s failed.", node->GetName().c_str());
     966              :         continue;
     967              :       }
     968              :       if (GraphUtils::RemoveNodeWithoutRelink(graph, node) != GRAPH_SUCCESS) {
     969              :         GELOGW("Remove node: %s failed.", node->GetName().c_str());
     970              :         continue;
     971              :       }
     972              :     }
     973              :   }
     974              : }
     975              : 
     976              : graphStatus TransOpWithoutReshapeFusionPass::Run(ComputeGraphPtr graph) {
     977              :   GELOGI("[TransOpWithoutReshapeFusionPass]: optimize begin.");
     978              :   if (graph == nullptr) {
     979              :     return GRAPH_SUCCESS;
     980              :   }
     981              : 
     982              :   for (const auto &node : graph->GetDirectNode()) {
     983              :     GE_CHECK_NOTNULL(node);
     984              :     if (IsTransOp(node)) {
     985              :       continue;
     986              :     }
     987              :     bool is_unknown = false;
     988              :     auto ret = NodeUtils::GetNodeUnknownShapeStatus(*node, is_unknown);
     989              :     if (ret != GRAPH_SUCCESS) {
     990              :       GELOGW("Get node unknown status failed, node name:%s, type:%s.", node->GetName().c_str(),
     991              :              node->GetType().c_str());
     992              :       continue;
     993              :     }
     994              :     if (is_unknown) {
     995              :       GELOGI("Current node %s, type %s is unknown shape which should be skip.", node->GetName().c_str(),
     996              :              node->GetType().c_str());
     997              :       continue;
     998              :     }
     999              :     GELOGD("Current normal node name: %s, type: %s.", node->GetName().c_str(), node->GetType().c_str());
    1000              :     for (const auto &out_anchor : node->GetAllOutDataAnchors()) {
    1001              :       GE_CHECK_NOTNULL(out_anchor);
    1002              :       std::vector<std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>>> sub_graph_anchors;
    1003              :       std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> nodes_list;
    1004              :       if (GetSubGraphsBetweenNormalNode(out_anchor, sub_graph_anchors, nodes_list) != GRAPH_SUCCESS) {
    1005              :         GELOGW("get transops failed!");
    1006              :         continue;
    1007              :       }
    1008              : 
    1009              :       sub_graph_anchors_.swap(sub_graph_anchors);
    1010              :       EraseInvalidAnchorsPair();
    1011              :       if (sub_graph_anchors_.empty()) {
    1012              :         continue;
    1013              :       }
    1014              : 
    1015              :       // check reshape node
    1016              :       if (GetSubGraphNodesInfo() != GRAPH_SUCCESS) {
    1017              :         continue;
    1018              :       }
    1019              : 
    1020              :       // save control edge
    1021              :       GetControlAnchors();
    1022              : 
    1023              :       if (TransOpFuse(graph) != GRAPH_SUCCESS) {
    1024              :         return GRAPH_FAILED;
    1025              :       }
    1026              :     }
    1027              :   }
    1028              :   GELOGI("[TransOpWithoutReshapeFusionPass]: Optimize end.");
    1029              :   return GRAPH_SUCCESS;
    1030              : }
    1031              : 
    1032              : bool TransOpWithoutReshapeFusionPass::DescEqualCheck(ConstGeTensorDescPtr &desc_src,
    1033              :                                                      ConstGeTensorDescPtr &desc_dst) const {
    1034              :   if ((desc_src == nullptr) || (desc_dst == nullptr)) {
    1035              :     return false;
    1036              :   }
    1037              :   if ((desc_src->GetFormat() != desc_dst->GetFormat()) || (desc_src->GetDataType() != desc_dst->GetDataType())) {
    1038              :     return false;
    1039              :   }
    1040              : 
    1041              :   if (!ShapeEqualCheck(desc_src->GetShape(), desc_dst->GetShape())) {
    1042              :     return false;
    1043              :   }
    1044              : 
    1045              :   return ShapeEqualCheck(desc_src->GetOriginShape(), desc_dst->GetOriginShape());
    1046              : }
    1047              : 
    1048              : bool TransOpWithoutReshapeFusionPass::ShapeEqualCheck(const GeShape &src, const GeShape &dst) const {
    1049              :   if (src.GetDims().size() != dst.GetDims().size()) {
    1050              :     return false;
    1051              :   }
    1052              : 
    1053              :   for (size_t i = 0; i < src.GetDims().size(); ++i) {
    1054              :     if (src.GetDim(i) != dst.GetDim(i)) {
    1055              :       return false;
    1056              :     }
    1057              :   }
    1058              :   return true;
    1059              : }
    1060              : 
    1061              : graphStatus TransOpWithoutReshapeFusionPass::TransOpFuse(const ComputeGraphPtr &graph) {
    1062              :   for (size_t i = 0; i < sub_graph_anchors_.size(); ++i) {
    1063              :     if (sub_graph_has_reshape_node_[i]) {
    1064              :       continue;
    1065              :     }
    1066              : 
    1067              :     auto nodes_anchor = sub_graph_anchors_[i];
    1068              :     auto out_anchor = nodes_anchor.front().first;
    1069              :     GE_CHECK_NOTNULL(out_anchor);
    1070              :     auto out_op_desc = out_anchor->GetOwnerNode()->GetOpDesc();
    1071              :     GE_CHECK_NOTNULL(out_op_desc);
    1072              :     auto out_desc = out_op_desc->GetOutputDescPtr(out_anchor->GetIdx());
    1073              :     GE_CHECK_NOTNULL(out_desc);
    1074              :     auto in_anchor = nodes_anchor.back().second;
    1075              :     GE_CHECK_NOTNULL(in_anchor);
    1076              :     auto in_op_desc = in_anchor->GetOwnerNode()->GetOpDesc();
    1077              :     GE_CHECK_NOTNULL(in_op_desc);
    1078              :     auto in_desc = in_op_desc->GetInputDescPtr(in_anchor->GetIdx());
    1079              :     GE_CHECK_NOTNULL(in_desc);
    1080              :     if (FusionFormatSupport(out_desc->GetFormat()) && DescEqualCheck(out_desc, in_desc)) {
    1081              :       // relink begin_out to end_in
    1082              :       if (RelinkNodesWhenDescNotChanged(nodes_anchor.front(), nodes_anchor.back(), static_cast<int32_t>(i)) !=
    1083              :           GRAPH_SUCCESS) {
    1084              :         return GRAPH_FAILED;
    1085              :       }
    1086              :     } else {
    1087              :       if (TransOpFuseHandle(graph, static_cast<int32_t>(i)) != GRAPH_SUCCESS) {
    1088              :         return GRAPH_FAILED;
    1089              :       }
    1090              :     }
    1091              :   }
    1092              :   RemoveNousedNodes(graph);
    1093              :   return GRAPH_SUCCESS;
    1094              : }
    1095              : 
    1096              : graphStatus TransOpWithoutReshapeFusionPass::AddTransNode(const ComputeGraphPtr &graph, const OpDescPtr &transop,
    1097              :                                                           NodePtr &trans_node) const {
    1098              :   if (graph == nullptr) {
    1099              :     return GRAPH_SUCCESS;
    1100              :   }
    1101              :   if (transop == nullptr) {
    1102              :     return GRAPH_SUCCESS;
    1103              :   }
    1104              : 
    1105              :   trans_node = graph->AddNode(transop);
    1106              :   if (trans_node == nullptr) {
    1107              :     REPORT_INNER_ERR_MSG("E19999", "Add node:%s(%s) to graph:%s failed", transop->GetName().c_str(),
    1108              :                          transop->GetType().c_str(), graph->GetName().c_str());
    1109              :     GELOGE(GRAPH_FAILED, "[Add][Node] %s(%s) to graph:%s failed", transop->GetName().c_str(),
    1110              :            transop->GetType().c_str(), graph->GetName().c_str());
    1111              :     return GRAPH_FAILED;
    1112              :   }
    1113              :   return GRAPH_SUCCESS;
    1114              : }
    1115              : 
    1116              : graphStatus TransOpWithoutReshapeFusionPass::GetTransNode(const ComputeGraphPtr &graph, const OpDescPtr &cast_op,
    1117              :                                                           const OpDescPtr &format_transfer_op,
    1118              :                                                           const bool insert_cast_first,
    1119              :                                                           std::vector<NodePtr> &new_trans_nodes) const {
    1120              :   NodePtr format_transfer_node;
    1121              :   if (AddTransNode(graph, format_transfer_op, format_transfer_node) != GRAPH_SUCCESS) {
    1122              :     return GRAPH_FAILED;
    1123              :   }
    1124              : 
    1125              :   NodePtr cast_node;
    1126              :   if (AddTransNode(graph, cast_op, cast_node) != GRAPH_SUCCESS) {
    1127              :     return GRAPH_FAILED;
    1128              :   }
    1129              : 
    1130              :   if (insert_cast_first) {
    1131              :     if (cast_node != nullptr) {
    1132              :       new_trans_nodes.push_back(cast_node);
    1133              :     }
    1134              :     if (format_transfer_node != nullptr) {
    1135              :       new_trans_nodes.push_back(format_transfer_node);
    1136              :     }
    1137              :   } else {
    1138              :     if (format_transfer_node != nullptr) {
    1139              :       new_trans_nodes.push_back(format_transfer_node);
    1140              :     }
    1141              :     if (cast_node != nullptr) {
    1142              :       new_trans_nodes.push_back(cast_node);
    1143              :     }
    1144              :   }
    1145              :   return GRAPH_SUCCESS;
    1146              : }
    1147              : 
    1148              : graphStatus TransOpWithoutReshapeFusionPass::InsertNewTransOp(const ComputeGraphPtr &graph, const OpDescPtr &cast_op,
    1149              :                                                               const OpDescPtr &format_transfer_op, const int32_t index,
    1150              :                                                               const bool insert_cast_first) {
    1151              :   std::vector<NodePtr> new_trans_nodes;
    1152              :   if (GetTransNode(graph, cast_op, format_transfer_op, insert_cast_first, new_trans_nodes) != GRAPH_SUCCESS) {
    1153              :     return GRAPH_FAILED;
    1154              :   }
    1155              :   if (new_trans_nodes.empty()) {
    1156              :     GELOGI("No new trans node. Do not need insert new transop.");
    1157              :     return GRAPH_SUCCESS;
    1158              :   }
    1159              : 
    1160              :   std::pair<OutDataAnchorPtr, InDataAnchorPtr> begin_out = sub_graph_anchors_[index].front();
    1161              :   std::pair<OutDataAnchorPtr, InDataAnchorPtr> end_in = sub_graph_anchors_[index].back();
    1162              :   auto out_anchor = begin_out.first;
    1163              :   GE_CHECK_NOTNULL(out_anchor);
    1164              :   auto out_owner_node = out_anchor->GetOwnerNode();
    1165              :   GE_CHECK_NOTNULL(out_owner_node);
    1166              :   auto in_anchor = end_in.second;
    1167              :   GE_CHECK_NOTNULL(in_anchor);
    1168              :   auto in_owner_node = in_anchor->GetOwnerNode();
    1169              :   GE_CHECK_NOTNULL(in_owner_node);
    1170              :   GELOGI("remove edge.src:%s, src idx:%d, dst:%s, dst idx:%d", end_in.first->GetOwnerNode()->GetName().c_str(),
    1171              :          end_in.first->GetIdx(), in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetIdx());
    1172              :   GE_CHK_STATUS_RET(GraphUtils::RemoveEdge(end_in.first, in_anchor), "[Remove][Edge] between %s and %s failed",
    1173              :                     out_owner_node->GetName().c_str(), in_owner_node->GetName().c_str());
    1174              :   GELOGI("add edge.src:%s, src idx:%d, dst:%s", out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetIdx(),
    1175              :          new_trans_nodes.front()->GetName().c_str());
    1176              :   if (GraphUtils::AddEdge(out_anchor, new_trans_nodes.front()->GetInAnchor(0)) != GRAPH_SUCCESS) {
    1177              :     REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:%d) and op:%s(%s)(index:0) failed",
    1178              :                          out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
    1179              :                          new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1180              :     GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:%d) and op:%s(%s)(index:0) failed",
    1181              :            out_owner_node->GetName().c_str(), out_owner_node->GetType().c_str(), out_anchor->GetIdx(),
    1182              :            new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1183              :     return GRAPH_FAILED;
    1184              :   } else {
    1185              :     auto old_peer_in_anchor = begin_out.second;
    1186              :     GE_CHECK_NOTNULL(old_peer_in_anchor);
    1187              :     UpdateOutputName(out_anchor, old_peer_in_anchor, in_owner_node);
    1188              :   }
    1189              : 
    1190              :   if (new_trans_nodes.size() > 1) {
    1191              :     GELOGI("add edge.src:%s, dst:%s", new_trans_nodes.front()->GetName().c_str(),
    1192              :            new_trans_nodes.back()->GetName().c_str());
    1193              :     if (GraphUtils::AddEdge(new_trans_nodes.front()->GetOutAnchor(0), new_trans_nodes.back()->GetInAnchor(0)) !=
    1194              :         GRAPH_SUCCESS) {
    1195              :       REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
    1196              :                            new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
    1197              :                            new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str());
    1198              :       GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:0) failed",
    1199              :              new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
    1200              :              new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str());
    1201              :       return GRAPH_FAILED;
    1202              :     } else {
    1203              :       auto old_peer_out_anchor = end_in.first;
    1204              :       GE_CHECK_NOTNULL(old_peer_out_anchor);
    1205              :       UpdateInputName(old_peer_out_anchor, in_anchor, out_owner_node);
    1206              :     }
    1207              :   }
    1208              :   GELOGI("add edge.src:%s, dst:%s, dst idx:%d", new_trans_nodes.back()->GetName().c_str(),
    1209              :          in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetIdx());
    1210              :   if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutAnchor(0), in_anchor) != GRAPH_SUCCESS) {
    1211              :     REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
    1212              :                          new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
    1213              :                          in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
    1214              :     GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
    1215              :            new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str(),
    1216              :            in_owner_node->GetName().c_str(), in_owner_node->GetType().c_str(), in_anchor->GetIdx());
    1217              :     return GRAPH_FAILED;
    1218              :   }
    1219              : 
    1220              :   return RelinkControlEdge(index, out_anchor, new_trans_nodes);
    1221              : }
    1222              : 
    1223            1 : bool TransOpWithoutReshapeFusionPass::CheckIfHasSameOutControlEdge(const NodePtr node, const NodePtr out_node) const {
    1224              :   auto out_anchor = node->GetOutControlAnchor();
    1225              :   for (auto peer_in_anchor : out_anchor->GetPeerInControlAnchors()) {
    1226              :     if (peer_in_anchor->GetOwnerNode() == out_node) {
    1227              :       return true;
    1228              :     }
    1229              :   }
    1230              :   return false;
    1231              : }
    1232              : 
    1233              : graphStatus TransOpWithoutReshapeFusionPass::AddControlEdgeForNewTransNode(
    1234              :     const int32_t index, const std::vector<NodePtr> &new_trans_nodes) {
    1235              :   for (const auto &peer_in_anchor : out_control_peer_in_control_anchors_[index]) {
    1236              :     GE_CHECK_NOTNULL(peer_in_anchor);
    1237              :     if (remain_in_control_anchors_.count(peer_in_anchor) > 0) {
    1238              :       continue;
    1239              :     }
    1240              :     GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
    1241              :            peer_in_anchor->GetOwnerNode()->GetName().c_str());
    1242              :     if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
    1243              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
    1244              :                            new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1245              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
    1246              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str());
    1247              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
    1248              :              new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1249              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
    1250              :       return GRAPH_FAILED;
    1251              :     }
    1252              :   }
    1253              : 
    1254              :   for (const auto &peer_out_anchor : in_control_peer_out_control_anchors_[index]) {
    1255              :     GE_CHECK_NOTNULL(peer_out_anchor);
    1256              :     if (remain_out_control_anchors_.count(peer_out_anchor) > 0) {
    1257              :       continue;
    1258              :     }
    1259              :     if (CheckIfHasSameOutControlEdge(new_trans_nodes.front(), peer_out_anchor->GetOwnerNode())) {
    1260              :       continue;
    1261              :     }
    1262              :     GELOGI("add control edge.src:%s, dst:%s", peer_out_anchor->GetOwnerNode()->GetName().c_str(),
    1263              :            new_trans_nodes.front()->GetName().c_str());
    1264              :     if (GraphUtils::AddEdge(peer_out_anchor, new_trans_nodes.front()->GetInControlAnchor()) != GRAPH_SUCCESS) {
    1265              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
    1266              :                            peer_out_anchor->GetOwnerNode()->GetName().c_str(),
    1267              :                            peer_out_anchor->GetOwnerNode()->GetType().c_str(),
    1268              :                            new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1269              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
    1270              :              peer_out_anchor->GetOwnerNode()->GetName().c_str(), peer_out_anchor->GetOwnerNode()->GetType().c_str(),
    1271              :              new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1272              :       return GRAPH_FAILED;
    1273              :     }
    1274              :   }
    1275              : 
    1276              :   // deprecated, there is no control anchor link to data anchor
    1277              :   for (const auto &peer_in_anchor : out_control_peer_in_data_anchors_[index]) {
    1278              :     GE_CHECK_NOTNULL(peer_in_anchor);
    1279              :     GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
    1280              :            peer_in_anchor->GetOwnerNode()->GetName().c_str());
    1281              :     if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutControlAnchor(), peer_in_anchor) != GRAPH_SUCCESS) {
    1282              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
    1283              :                            new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1284              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
    1285              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str());
    1286              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
    1287              :              new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1288              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str());
    1289              :       return GRAPH_FAILED;
    1290              :     }
    1291              :   }
    1292              : 
    1293              :   // deprecated, there is no control anchor link to data anchor
    1294              :   for (const auto &peer_in_anchor : out_data_peer_in_control_anchors_[index]) {
    1295              :     GE_CHECK_NOTNULL(peer_in_anchor);
    1296              :     GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
    1297              :            peer_in_anchor->GetOwnerNode()->GetName().c_str());
    1298              :     if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutDataAnchor(0), peer_in_anchor) != GRAPH_SUCCESS) {
    1299              :       REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
    1300              :                            new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1301              :                            peer_in_anchor->GetOwnerNode()->GetName().c_str(),
    1302              :                            peer_in_anchor->GetOwnerNode()->GetType().c_str(), peer_in_anchor->GetIdx());
    1303              :       GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s)(index:0) and op:%s(%s)(index:%d) failed",
    1304              :              new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1305              :              peer_in_anchor->GetOwnerNode()->GetName().c_str(), peer_in_anchor->GetOwnerNode()->GetType().c_str(),
    1306              :              peer_in_anchor->GetIdx());
    1307              :       return GRAPH_FAILED;
    1308              :     }
    1309              :   }
    1310              :   return GRAPH_SUCCESS;
    1311              : }
    1312              : 
    1313              : graphStatus TransOpWithoutReshapeFusionPass::RelinkControlEdge(const int32_t index, const OutDataAnchorPtr &out_anchor,
    1314              :                                                                const std::vector<NodePtr> &new_trans_nodes) {
    1315              :   GE_CHECK_NOTNULL(out_anchor);
    1316              :   if (sub_graph_has_control_edge_[index]) {
    1317              :     GELOGI("add control edge.src:%s, dst:%s", out_anchor->GetOwnerNode()->GetName().c_str(),
    1318              :            new_trans_nodes.front()->GetName().c_str());
    1319              :     if (GraphUtils::AddEdge(out_anchor->GetOwnerNode()->GetOutControlAnchor(),
    1320              :                             new_trans_nodes.front()->GetInControlAnchor()) != GRAPH_SUCCESS) {
    1321              :       REPORT_INNER_ERR_MSG("E19999", "Add control edge between op:%s(%s) and op:%s(%s) failed",
    1322              :                            out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetOwnerNode()->GetType().c_str(),
    1323              :                            new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1324              :       GELOGE(GRAPH_FAILED, "[Add][ControlEdge] between op:%s(%s) and op:%s(%s) failed",
    1325              :              out_anchor->GetOwnerNode()->GetName().c_str(), out_anchor->GetOwnerNode()->GetType().c_str(),
    1326              :              new_trans_nodes.front()->GetName().c_str(), new_trans_nodes.front()->GetType().c_str());
    1327              :       return GRAPH_FAILED;
    1328              :     }
    1329              :   }
    1330              :   if (AddControlEdgeForNewTransNode(index, new_trans_nodes) == GRAPH_FAILED) {
    1331              :     return GRAPH_FAILED;
    1332              :   }
    1333              :   if (sub_graph_has_out_data_peer_in_control_edge_[index]) {
    1334              :     auto in_anchor = sub_graph_anchors_[index].back().second;
    1335              :     GELOGI("add control edge.src:%s, dst:%s", new_trans_nodes.back()->GetName().c_str(),
    1336              :            in_anchor->GetOwnerNode()->GetName().c_str());
    1337              :     if (GraphUtils::AddEdge(new_trans_nodes.back()->GetOutDataAnchor(0),
    1338              :                             in_anchor->GetOwnerNode()->GetInControlAnchor()) != GRAPH_SUCCESS) {
    1339              :       REPORT_INNER_ERR_MSG("E19999", "Add edge between op:%s(%s) and op:%s(%s) failed",
    1340              :                            new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1341              :                            in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetOwnerNode()->GetType().c_str());
    1342              :       GELOGE(GRAPH_FAILED, "[Add][Edge] between op:%s(%s) and op:%s(%s) failed",
    1343              :              new_trans_nodes.back()->GetName().c_str(), new_trans_nodes.back()->GetType().c_str(),
    1344              :              in_anchor->GetOwnerNode()->GetName().c_str(), in_anchor->GetOwnerNode()->GetType().c_str());
    1345              :       return GRAPH_FAILED;
    1346              :     }
    1347              :   }
    1348              :   return GRAPH_SUCCESS;
    1349              : }
    1350              : 
    1351              : bool TransOpWithoutReshapeFusionPass::FusionFormatSupport(Format format) {
    1352              :   const auto primary_format = static_cast<Format>(GetPrimaryFormat(static_cast<int32_t>(format)));
    1353              :   return primary_format == FORMAT_NCHW || primary_format == FORMAT_NHWC || primary_format == FORMAT_FRACTAL_Z ||
    1354              :          primary_format == FORMAT_NC1HWC0;
    1355              : }
    1356              : 
    1357              : graphStatus TransOpWithoutReshapeFusionPass::GetSubGraphsBetweenNormalNode(
    1358              :     const OutDataAnchorPtr &out_anchor,
    1359              :     std::vector<std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>>> &sub_graphs_out,
    1360              :     std::vector<std::pair<OutDataAnchorPtr, InDataAnchorPtr>> &nodes_list) {
    1361              :   graphStatus ret = GRAPH_SUCCESS;
    1362              :   if (out_anchor == nullptr) {
    1363              :     REPORT_INNER_ERR_MSG("E19999", "Param out_anchor is nullptr, check invalid");
    1364              :     GELOGE(GRAPH_FAILED, "[Check][Param] param out_anchor is nullptr");
    1365              :     return GRAPH_FAILED;
    1366              :   }
    1367              : 
    1368              :   for (const auto &peer_in_anchor : out_anchor->GetPeerInDataAnchors()) {
    1369              :     if (peer_in_anchor == nullptr || peer_in_anchor->GetOwnerNode() == nullptr ||
    1370              :         peer_in_anchor->GetOwnerNode()->GetOpDesc() == nullptr) {
    1371              :       continue;
    1372              :     }
    1373              : 
    1374              :     nodes_list.emplace_back(out_anchor, peer_in_anchor);
    1375              :     auto peer_in_node = peer_in_anchor->GetOwnerNode();
    1376              :     GE_CHECK_NOTNULL(peer_in_node);
    1377              :     if (!IsTransOp(peer_in_node)) {
    1378              :       sub_graphs_out.push_back(nodes_list);
    1379              :       nodes_list.pop_back();
    1380              :     } else {
    1381              :       for (const auto &peer_out_anchor : peer_in_node->GetAllOutDataAnchors()) {
    1382              :         ret = GetSubGraphsBetweenNormalNode(peer_out_anchor, sub_graphs_out, nodes_list);
    1383              :         if (ret != GRAPH_SUCCESS) {
    1384              :           GELOGE(GRAPH_FAILED, "[Get][SubGraphs] Between Normal Node failed! node:%s", peer_in_node->GetName().c_str());
    1385              :           return GRAPH_FAILED;
    1386              :         }
    1387              :       }
    1388              :       nodes_list.pop_back();
    1389              :     }
    1390              :   }
    1391              :   return GRAPH_SUCCESS;
    1392              : }
    1393              : 
    1394              : bool TransOpWithoutReshapeFusionPass::IsTransOp(const NodePtr &node) {
    1395              :   return IsTransOp(node.get());
    1396              : }
    1397              : 
    1398              : bool TransOpWithoutReshapeFusionPass::IsTransOp(const Node *node) {
    1399              :   // The caller guarantees that the pointer is not null.
    1400              :   return node->GetType() == CAST || node->GetType() == RESHAPE || node->GetType() == TRANSPOSE ||
    1401              :          node->GetType() == TRANSPOSED || node->GetType() == TRANSDATA;
    1402              : }
    1403              : 
    1404              : REG_PASS_OPTION("TransOpWithoutReshapeFusionPass").LEVELS(OoLevel::kO3);
    1405              : }  // namespace ge
        

Generated by: LCOV version 2.3.2-1