已合并
【PR】: [feat] [autofuse] optimization of gaf open headers. #1087
【PR】: [feat] [autofuse] optimization of gaf open headers. #1087
已合并
邢智雄创建于 6月26日
共 15 个文件变更+233-70
@@ -278,21 +278,21 @@ install(FILES
278 278 
279install(FILES279install(FILES
280 ${CODE_ROOT_DIR}/ascir/meta/ascend_graph_code_dumper.h280 ${CODE_ROOT_DIR}/ascir/meta/ascend_graph_code_dumper.h
281- DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/ascir/meta281+ DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/ascir/meta
282- COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}282+ COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}
283)283)
284 284 
285install(FILES285install(FILES
286 ${CODE_ROOT_DIR}/common/common_utils.h286 ${CODE_ROOT_DIR}/common/common_utils.h
287 ${CODE_ROOT_DIR}/common/schedule_result.h287 ${CODE_ROOT_DIR}/common/schedule_result.h
288- DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/common288+ DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/common
289- COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}289+ COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}
290)290)
291 291 
292install(FILES292install(FILES
293 ${CODE_ROOT_DIR}/att/base/base_types.h293 ${CODE_ROOT_DIR}/att/base/base_types.h
294- DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/base294+ DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/base
295- COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}295+ COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}
296)296)
297 297 
298install(FILES298install(FILES
@@ -351,8 +351,8 @@ install(FILES ${CODE_ROOT_DIR}/inc/graph_metadef/graph/debug/ge_util.h
351install(FILES351install(FILES
352 ${CODE_ROOT_DIR}/ascir/meta/ascir.h352 ${CODE_ROOT_DIR}/ascir/meta/ascir.h
353 ${CODE_ROOT_DIR}/ascir/meta/ascir_ops_utils.h353 ${CODE_ROOT_DIR}/ascir/meta/ascir_ops_utils.h
354- DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/ascir/meta354+ DESTINATION ${AUTOFUSE_INSTALL_INCLUDE_DIR}/ascir/meta
355- COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}355+ COMPONENT ${AUTOFUSE_INSTALL_COMPONENT}
356)356)
357 357 
358# generated ascir_ops.h (produced by ascir_builtin_ops_header at build time)358# generated ascir_ops.h (produced by ascir_builtin_ops_header at build time)
@@ -0,0 +1,38 @@
1+/**
2+ * Copyright (c) 2026 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 "common/autofuse_backend_spec_api.h"
12+ 
13+#include "backend/backend_spec.h"
14+ 
15+namespace ge {
16+std::unique_ptr<AutofuseBackendSpec> GetAutofuseBackendSpec() {
17+ const auto backend_spec = optimize::BackendSpec::GetInstance();
18+ if (backend_spec == nullptr) {
19+ return nullptr;
20+ }
21+ 
22+ auto spec = std::make_unique<AutofuseBackendSpec>();
23+ spec->concat_max_input_num = backend_spec->concat_max_input_num;
24+ spec->concat_alg = backend_spec->concat_alg;
25+ spec->gather_spec = {
26+ backend_spec->gather_spec.enable_non_tail_gather, backend_spec->gather_spec.enable_reduce_gather_fusion,
27+ backend_spec->gather_spec.enable_gather_concat_fusion, backend_spec->gather_spec.enable_gather_broadcast_fusion,
28+ backend_spec->gather_spec.enable_gather_elementwise_forward_fusion};
29+ spec->slice_split_spec = {backend_spec->slice_split_spec.split_lowered_to_split,
30+ backend_spec->slice_split_spec.slice_fuse_with_end_dim_1,
31+ backend_spec->slice_split_spec.enable_split_flatten};
32+ spec->max_load_num = backend_spec->max_load_num;
33+ spec->max_input_nums_after_fuse = backend_spec->max_input_nums_after_fuse;
34+ spec->transpose_mode = backend_spec->transpose_mode;
35+ spec->enable_matmul_lowering_to_matmul = backend_spec->enable_matmul_lowering_to_matmul;
36+ return spec;
37+}
38+} // namespace ge
@@ -0,0 +1,51 @@
1+/**
2+ * Copyright (c) 2026 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+#ifndef ASCGEN_DEV_BASE_COMMON_AUTOFUSE_BACKEND_SPEC_API_H_
12+#define ASCGEN_DEV_BASE_COMMON_AUTOFUSE_BACKEND_SPEC_API_H_
13+ 
14+#include <cstdint>
15+#include <memory>
16+ 
17+namespace ge {
18+struct AutofuseGatherSpec {
19+ bool enable_non_tail_gather = false;
20+ bool enable_reduce_gather_fusion = false;
21+ bool enable_gather_concat_fusion = false;
22+ bool enable_gather_broadcast_fusion = false;
23+ bool enable_gather_elementwise_forward_fusion = false;
24+};
25+ 
26+struct AutofuseSliceSplitSpec {
27+ bool split_lowered_to_split = false;
28+ bool slice_fuse_with_end_dim_1 = false;
29+ bool enable_split_flatten = false;
30+};
31+ 
32+enum class AutofuseTransposeMode : uint32_t {
33+ TRANSPOSE_MODE_NORMAL = 0,
34+ TRANSPOSE_MODE_UNNORMAL = 1,
35+};
36+ 
37+struct AutofuseBackendSpec {
38+ uint32_t concat_max_input_num = 0U;
39+ int32_t concat_alg = 0;
40+ AutofuseGatherSpec gather_spec;
41+ AutofuseSliceSplitSpec slice_split_spec;
42+ uint32_t max_load_num = 0U;
43+ uint32_t max_input_nums_after_fuse = 8U;
44+ uint32_t transpose_mode = static_cast<uint32_t>(AutofuseTransposeMode::TRANSPOSE_MODE_NORMAL);
45+ bool enable_matmul_lowering_to_matmul = false;
46+};
47+ 
48+std::unique_ptr<AutofuseBackendSpec> GetAutofuseBackendSpec();
49+} // namespace ge
50+ 
51+#endif // ASCGEN_DEV_BASE_COMMON_AUTOFUSE_BACKEND_SPEC_API_H_
@@ -0,0 +1,27 @@
1+/**
2+ * Copyright (c) 2026 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 "common/autofuse_platform_api.h"
12+#include "common/platform_context.h"
13+ 
14+namespace ge {
15+ge::Status SetAutofusePlatform(const std::string &platform_name) {
16+ PlatformContext::GetInstance().SetPlatform(platform_name);
17+ return ge::SUCCESS;
18+}
19+ 
20+ge::Status GetAutofusePlatform(std::string &platform_name) {
21+ return PlatformContext::GetInstance().GetCurrentPlatformString(platform_name);
22+}
23+ 
24+void ResetAutofusePlatform() {
25+ PlatformContext::GetInstance().Reset();
26+}
27+} // namespace ge
@@ -0,0 +1,23 @@
1+/**
2+ * Copyright (c) 2026 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+#ifndef ASCGEN_DEV_BASE_COMMON_AUTOFUSE_PLATFORM_API_H_
12+#define ASCGEN_DEV_BASE_COMMON_AUTOFUSE_PLATFORM_API_H_
13+ 
14+#include <string>
15+#include "ge_common/ge_api_error_codes.h"
16+ 
17+namespace ge {
18+ge::Status SetAutofusePlatform(const std::string &platform_name);
19+ge::Status GetAutofusePlatform(std::string &platform_name);
20+void ResetAutofusePlatform();
21+} // namespace ge
22+ 
23+#endif // ASCGEN_DEV_BASE_COMMON_AUTOFUSE_PLATFORM_API_H_
@@ -15,8 +15,8 @@
15#include "ascir_ops.h"15#include "ascir_ops.h"
16#include "ascir_ops_utils.h"16#include "ascir_ops_utils.h"
17#include "ascgen_log.h"17#include "ascgen_log.h"
18+#include "graph/utils/type_utils.h"
18#include "graph/ascendc_ir/utils/asc_graph_utils.h"19#include "graph/ascendc_ir/utils/asc_graph_utils.h"
19-#include "fusion/loop_types.h"
20#include "common/platform_context.h"20#include "common/platform_context.h"
21 21 
22#include "pyascir_types.h"22#include "pyascir_types.h"
@@ -35,6 +35,17 @@ std::map<std::string, pyascir::InferDtypeFunc> kInferDtypeFuncs = {
35#undef OP35#undef OP
36};36};
37namespace {37namespace {
38+std::string DataTypesToString(const std::vector<af::DataType> &dtypes) {
39+ if (dtypes.empty()) {
40+ return "[]";
41+ }
42+ std::string result = "[" + ge::TypeUtils::DataTypeToSerialString(dtypes[0]);
43+ for (size_t i = 1U; i < dtypes.size(); ++i) {
44+ result += ", " + ge::TypeUtils::DataTypeToSerialString(dtypes[i]);
45+ }
46+ return result + "]";
47+}
48+ 
38InferDtypeFunc GetInferDtypeFunc(const std::string &node_type) {49InferDtypeFunc GetInferDtypeFunc(const std::string &node_type) {
39 auto iter = kInferDtypeFuncs.find(node_type);50 auto iter = kInferDtypeFuncs.find(node_type);
40 PY_ASSERT(iter != kInferDtypeFuncs.end(), "%s has no infer dtype func", node_type.c_str());51 PY_ASSERT(iter != kInferDtypeFuncs.end(), "%s has no infer dtype func", node_type.c_str());
@@ -171,15 +182,15 @@ bool DoDynamicOutputInference(const af::AscNodePtr &node, InferDtypeFunc infer_f
171 if (has_complete_output_dtypes) {182 if (has_complete_output_dtypes) {
172 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),183 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),
173 "Check dtype failed for %s %s; input_dtypes: %s, output_dytpes: %s", node->GetNamePtr(),184 "Check dtype failed for %s %s; input_dtypes: %s, output_dytpes: %s", node->GetNamePtr(),
174- node->GetTypePtr(), ge::loop::StrJoin(input_dtypes).c_str(),185+ node->GetTypePtr(), DataTypesToString(input_dtypes).c_str(),
175- ge::loop::StrJoin(output_dtyps).c_str());186+ DataTypesToString(output_dtyps).c_str());
176 return true;187 return true;
177 }188 }
178 189 
179 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),190 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),
180 "Infer dtype failed for %s %s; input_dtypes: %s is not supportted now", node->GetNamePtr(),191 "Infer dtype failed for %s %s; input_dtypes: %s is not supportted now", node->GetNamePtr(),
181- node->GetTypePtr(), ge::loop::StrJoin(input_dtypes).c_str(),192+ node->GetTypePtr(), DataTypesToString(input_dtypes).c_str(),
182- ge::loop::StrJoin(output_dtyps).c_str());193+ DataTypesToString(output_dtyps).c_str());
183 194 
184 PY_ASSERT_EQ(output_dtyps.size(), ir_outputs.size());195 PY_ASSERT_EQ(output_dtyps.size(), ir_outputs.size());
185 std::vector<af::DataType> expanded_output_dtypes;196 std::vector<af::DataType> expanded_output_dtypes;
@@ -222,14 +233,14 @@ bool DoInference(const af::AscNodePtr &node, InferDtypeFunc infer_func, const st
222 if (!for_infer) {233 if (!for_infer) {
223 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),234 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),
224 "Check dtype failed for %s %s; input_dtypes: %s, output_dytpes: %s", node->GetNamePtr(),235 "Check dtype failed for %s %s; input_dtypes: %s, output_dytpes: %s", node->GetNamePtr(),
225- node->GetTypePtr(), ge::loop::StrJoin(input_dtypes).c_str(),236+ node->GetTypePtr(), DataTypesToString(input_dtypes).c_str(),
226- ge::loop::StrJoin(output_dtyps).c_str());237+ DataTypesToString(output_dtyps).c_str());
227 return true;238 return true;
228 }239 }
229 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),240 PY_ASSERT_SUCCESS(infer_func(input_dtypes, output_dtyps, npu_arch),
230 "Infer dtype failed for %s %s; input_dtypes: %s is not supportted now", node->GetNamePtr(),241 "Infer dtype failed for %s %s; input_dtypes: %s is not supportted now", node->GetNamePtr(),
231- node->GetTypePtr(), ge::loop::StrJoin(input_dtypes).c_str(),242+ node->GetTypePtr(), DataTypesToString(input_dtypes).c_str(),
232- ge::loop::StrJoin(output_dtyps).c_str());243+ DataTypesToString(output_dtyps).c_str());
233 244 
234 PY_ASSERT_EQ(output_dtyps.size(), op_desc->GetOutputsSize());245 PY_ASSERT_EQ(output_dtyps.size(), op_desc->GetOutputsSize());
235 for (size_t i = 0UL; i < output_dtyps.size(); ++i) {246 for (size_t i = 0UL; i < output_dtyps.size(); ++i) {
@@ -18,8 +18,6 @@ enum class AutoFuseConfigType : int32_t {
18 ENV_CONFIG,18 ENV_CONFIG,
19 INVALID_CONFIG_TYPE,19 INVALID_CONFIG_TYPE,
20};20};
21- 
22-enum class AutoFuseFwkType : int32_t { kDefault = 0, kGe, kTorch };
23} // namespace ge21} // namespace ge
24 22 
25#endif // ATT_CXX_AUTOFUSE_BASE_TYPE_H23#endif // ATT_CXX_AUTOFUSE_BASE_TYPE_H
@@ -11,10 +11,14 @@
11#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_AUTOFUSE_ATTRS_H_11#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_AUTOFUSE_ATTRS_H_
12#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_AUTOFUSE_ATTRS_H_12#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_AUTOFUSE_ATTRS_H_
13 13 
14+#include <map>
14#include <memory>15#include <memory>
16+#include <set>
17+#include <string>
18+#include <utility>
15#include <vector>19#include <vector>
16 20 
17-#include "fusion/loop_types.h"21+#include "fusion/fuse_type.h"
18#include "fusion/fusion_decider.h"22#include "fusion/fusion_decider.h"
19#include "autoschedule/axis_group.h"23#include "autoschedule/axis_group.h"
20#include "graph/debug/ge_attr_define.h"24#include "graph/debug/ge_attr_define.h"
Rautofuse/inc/fusion/loop_types.h→autofuse/inc/fusion/fuse_type.h+4-48
@@ -8,21 +8,11 @@
8 * See LICENSE in the root of the software repository for the full text of the License.8 * See LICENSE in the root of the software repository for the full text of the License.
9 */9 */
10 10 
11-#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_LOOP_TYPES_H_11+#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_FUSE_TYPE_H_
12-#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_LOOP_TYPES_H_12+#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_FUSE_TYPE_H_
13 13 
14+#include <cstdint>
14#include <string>15#include <string>
15-#include <vector>
16- 
17-#include "graph/symbolizer/symbolic.h"
18-#include "graph/utils/type_utils.h"
19- 
20-#ifdef AUTOFUSE_USE_GE_METADEF
21-namespace af {
22-using ge::Expression;
23-using ge::TypeUtils;
24-} // namespace af
25-#endif
26 16 
27namespace af {17namespace af {
28namespace loop {18namespace loop {
@@ -68,39 +58,6 @@ inline std::string FuseTypeToString(FuseType type) {
68 }58 }
69}59}
70 60 
71-template <typename T, typename F>
72-std::string StrJoin(const std::vector<T> &vec, F f, const std::string &sep = ", ") {
73- if (vec.empty()) {
74- return "[]";
75- }
76- std::string res = "[" + f(vec[0]);
77- for (size_t i = 1U; i < vec.size(); ++i) {
78- res += sep + f(vec[i]);
79- }
80- return res + "]";
81-}
82- 
83-inline std::string StrJoin(const std::vector<std::string> &vec, const std::string &sep = ", ") {
84- return StrJoin(vec, [](const std::string &s) { return s; }, sep);
85-}
86- 
87-inline std::string StrJoin(const std::vector<af::Expression> &vec, const std::string &sep = ", ") {
88- return StrJoin(vec, [](const af::Expression &s) { return std::string(s.Str().get()); }, sep);
89-}
90- 
91-inline std::string StrJoin(const std::vector<ge::DataType> &vec, const std::string &sep = ", ") {
92- return StrJoin(vec, [](const ge::DataType &s) { return TypeUtils::DataTypeToSerialString(s); }, sep);
93-}
94- 
95-inline std::string StrJoin(const std::vector<int64_t> &vec, const std::string &sep) {
96- return StrJoin(vec, [](const int64_t &s) { return std::to_string(s); }, sep);
97-}
98- 
99-template <typename T>
100-inline typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, std::string>::type StrJoin(
101- const std::vector<T> &vec, const std::string &sep = ", ") {
102- return StrJoin(vec, [](const T &s) { return std::to_string(s); }, sep);
103-}
104} // namespace loop61} // namespace loop
105} // namespace af62} // namespace af
106 63 
@@ -108,8 +65,7 @@ namespace ge {
108namespace loop {65namespace loop {
109using af::loop::FuseType;66using af::loop::FuseType;
110using af::loop::FuseTypeToString;67using af::loop::FuseTypeToString;
111-using af::loop::StrJoin;
112} // namespace loop68} // namespace loop
113} // namespace ge69} // namespace ge
114 70 
115-#endif // AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_LOOP_TYPES_H_71+#endif // AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_INC_FUSION_FUSE_TYPE_H_
@@ -195,6 +195,9 @@ cmake_print_variables(ENABLE_OPEN_SRC)
195####################################common############################################195####################################common############################################
196set(COMMON_DIR ${CODE_ROOT_DIR}/common)196set(COMMON_DIR ${CODE_ROOT_DIR}/common)
197file(GLOB_RECURSE CODEGEN_COMMON_SRCS CONFIGURE_DEPENDS "${COMMON_DIR}/*.cpp" "${COMMON_DIR}/*.cc")197file(GLOB_RECURSE CODEGEN_COMMON_SRCS CONFIGURE_DEPENDS "${COMMON_DIR}/*.cpp" "${COMMON_DIR}/*.cc")
198+list(REMOVE_ITEM CODEGEN_COMMON_SRCS
199+ "${COMMON_DIR}/autofuse_backend_spec_api.cpp"
200+)
198add_library(ascgen_common SHARED201add_library(ascgen_common SHARED
199 ${CODEGEN_COMMON_SRCS}202 ${CODEGEN_COMMON_SRCS}
200)203)
@@ -360,7 +363,7 @@ add_library(codegen SHARED
360 363 
361set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};${CODE_ROOT_DIR}/att/build")364set(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};${CODE_ROOT_DIR}/att/build")
362 365 
363-target_compile_options(codegen PRIVATE 366+target_compile_options(codegen PRIVATE
364 -Wfloat-equal -Wextra367 -Wfloat-equal -Wextra
365)368)
366 369 
@@ -3,6 +3,9 @@ file(GLOB_RECURSE COMMON_SRC_FILES CONFIGURE_DEPENDS
3 "${COMMON_ROOT_DIR}/*.cpp"3 "${COMMON_ROOT_DIR}/*.cpp"
4 "${COMMON_ROOT_DIR}/*.cc"4 "${COMMON_ROOT_DIR}/*.cc"
5)5)
6+list(REMOVE_ITEM COMMON_SRC_FILES
7+ "${COMMON_ROOT_DIR}/autofuse_backend_spec_api.cpp"
8+)
6 9 
7file(GLOB_RECURSE COMMON_TEST_SRCS CONFIGURE_DEPENDS "*.cpp" "*.cc")10file(GLOB_RECURSE COMMON_TEST_SRCS CONFIGURE_DEPENDS "*.cpp" "*.cc")
8add_executable(test_common11add_executable(test_common
@@ -42,4 +45,4 @@ target_link_libraries(test_common PRIVATE
42 json45 json
43 error_manager46 error_manager
44 metadef47 metadef
45-)48+)
@@ -40,6 +40,7 @@
40#include "all_ops_cpp.h"40#include "all_ops_cpp.h"
41#include "compliant_op_desc_builder.h"41#include "compliant_op_desc_builder.h"
42#include "esb_graph.h"42#include "esb_graph.h"
43+#include "loop_test_utils.h"
43#include "op_creator_register.h"44#include "op_creator_register.h"
44 45 
45using namespace std;46using namespace std;
@@ -27,6 +27,7 @@
27#include "post_process/scheduler_adapter/torch_adaption_fallback_load.h"27#include "post_process/scheduler_adapter/torch_adaption_fallback_load.h"
28#include "expression/testcase/source_stub.h"28#include "expression/testcase/source_stub.h"
29#include "depends/runtime/src/runtime_stub.h"29#include "depends/runtime/src/runtime_stub.h"
30+#include "loop_test_utils.h"
30 31 
31#include "platform_context.h"32#include "platform_context.h"
32 33 
@@ -0,0 +1,46 @@
1+/**
2+ * Copyright (c) 2026 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+#ifndef AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_TESTS_V35_UT_AUTOFUSE_LOOP_TEST_UTILS_H_
12+#define AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_TESTS_V35_UT_AUTOFUSE_LOOP_TEST_UTILS_H_
13+ 
14+#include <string>
15+#include <type_traits>
16+#include <vector>
17+ 
18+namespace af {
19+namespace loop {
20+ 
21+template <typename T, typename F>
22+std::string StrJoin(const std::vector<T> &vec, F f, const std::string &sep = ", ") {
23+ if (vec.empty()) {
24+ return "[]";
25+ }
26+ std::string res = "[" + f(vec[0]);
27+ for (size_t i = 1U; i < vec.size(); ++i) {
28+ res += sep + f(vec[i]);
29+ }
30+ return res + "]";
31+}
32+ 
33+inline std::string StrJoin(const std::vector<std::string> &vec, const std::string &sep = ", ") {
34+ return StrJoin(vec, [](const std::string &s) { return s; }, sep);
35+}
36+ 
37+template <typename T>
38+inline typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value, std::string>::type StrJoin(
39+ const std::vector<T> &vec, const std::string &sep = ", ") {
40+ return StrJoin(vec, [](const T &s) { return std::to_string(s); }, sep);
41+}
42+ 
43+} // namespace loop
44+} // namespace af
45+ 
46+#endif // AIR_CXX_COMPILER_GRAPH_OPTIMIZE_AUTOFUSE_TESTS_V35_UT_AUTOFUSE_LOOP_TEST_UTILS_H_
@@ -35,6 +35,7 @@
35#include "all_ops_cpp.h"35#include "all_ops_cpp.h"
36#include "compliant_op_desc_builder.h"36#include "compliant_op_desc_builder.h"
37#include "esb_graph.h"37#include "esb_graph.h"
38+#include "loop_test_utils.h"
38#include "platform_context.h"39#include "platform_context.h"
39#include "base/att_const_values.h"40#include "base/att_const_values.h"
40#include "depends/runtime/src/runtime_stub.h"41#include "depends/runtime/src/runtime_stub.h"