已合并
【feat】:v35 reduce全量迁移 #2118
guojianyang创建于 29 天前
【feat】:v35 reduce全量迁移 #2118
已合并
guojianyang创建于 29 天前
共 26 个文件变更+4526-10
@@ -54,6 +54,6 @@ TEST_F(TestBackendLoadCompareCastSumStoreE2e, LoadCompareCastSumStoreE2eCodegen)
54 EXPECT_NE(kernel.find("{static_cast<uint16_t>(((32 * Ceiling((Rational(1 , 32) * t->z2t_size))))/(1)), "54 EXPECT_NE(kernel.find("{static_cast<uint16_t>(((32 * Ceiling((Rational(1 , 32) * t->z2t_size))))/(1)), "
55 "static_cast<uint16_t>(1)}"),55 "static_cast<uint16_t>(1)}"),
56 std::string::npos);56 std::string::npos);
57- EXPECT_NE(kernel.find("ReduceSum<float, AscendC::Pattern::Reduce::RA, true>"), std::string::npos);57+ EXPECT_NE(kernel.find("ReduceSumExtend<float, AscendC::Pattern::Reduce::RA, true>"), std::string::npos);
58 });58 });
59}59}
@@ -14,6 +14,7 @@ add_library(test_regbase_ascendc OBJECT
14 ./test_min.cpp14 ./test_min.cpp
15 ./test_where.cpp15 ./test_where.cpp
16 ./test_reduce_init.cpp16 ./test_reduce_init.cpp
17+ ./test_reduce_extend.cpp
17 ./test_argmax.cpp18 ./test_argmax.cpp
18 ./test_add.cpp19 ./test_add.cpp
19 ./test_airy_ai.cpp20 ./test_airy_ai.cpp
@@ -88,4 +89,5 @@ target_link_libraries(test_regbase_ascendc
88target_include_directories(test_regbase_ascendc PUBLIC89target_include_directories(test_regbase_ascendc PUBLIC
89 ${CODE_ROOT_DIR}/ascendc90 ${CODE_ROOT_DIR}/ascendc
90 ${CODE_ROOT_DIR}/v35/ascendc91 ${CODE_ROOT_DIR}/v35/ascendc
92+ ${ASCEND_INSTALL_PATH}/${CMAKE_SYSTEM_PROCESSOR}-linux/asc/include
91)93)
@@ -0,0 +1,148 @@
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 <algorithm>
12+#include <cstdint>
13+#include <functional>
14+#include <numeric>
15+#include <vector>
16+ 
17+#include "gtest/gtest.h"
18+#include "tikicpulib.h"
19+#include "test_api_utils.h"
20+#include "api_regbase/reduce_extend.h"
21+ 
22+namespace {
23+constexpr uint32_t kTmpBufferSize = 32 * 1024;
24+ 
25+template <typename T, typename Pattern, typename ReduceFunc>
26+void RunReduceKernel(T *input, T *output, uint32_t inputCount, uint32_t outputCount, uint32_t dim0, uint32_t dim1,
27+ ReduceFunc reduce) {
28+ TPipe pipe;
29+ TBuf<TPosition::VECCALC> srcBuffer;
30+ TBuf<TPosition::VECCALC> dstBuffer;
31+ TBuf<TPosition::VECCALC> tmpBuffer;
32+ pipe.InitBuffer(srcBuffer, AlignUp(inputCount * sizeof(T), ONE_BLK_SIZE));
33+ pipe.InitBuffer(dstBuffer, AlignUp(outputCount * sizeof(T), ONE_BLK_SIZE));
34+ pipe.InitBuffer(tmpBuffer, kTmpBufferSize);
35+ 
36+ LocalTensor<T> src = srcBuffer.Get<T>();
37+ LocalTensor<T> dst = dstBuffer.Get<T>();
38+ LocalTensor<uint8_t> tmp = tmpBuffer.Get<uint8_t>();
39+ GmToUb(src, input, inputCount);
40+ 
41+ const uint32_t shape[] = {dim0, dim1};
42+ reduce(dst, src, tmp, shape);
43+ UbToGm(output, dst, outputCount);
44+}
45+ 
46+template <typename T, typename Pattern, typename ReduceFunc>
47+std::vector<T> RunReduce(const std::vector<T> &input, uint32_t outputCount, uint32_t dim0, uint32_t dim1,
48+ ReduceFunc reduce) {
49+ const uint32_t inputBytes = AlignUp(input.size() * sizeof(T), ONE_BLK_SIZE);
50+ const uint32_t outputBytes = AlignUp(outputCount * sizeof(T), ONE_BLK_SIZE);
51+ auto *inputGm = static_cast<T *>(AscendC::GmAlloc(inputBytes));
52+ auto *outputGm = static_cast<T *>(AscendC::GmAlloc(outputBytes));
53+ std::copy(input.begin(), input.end(), inputGm);
54+ std::fill_n(outputGm, outputBytes / sizeof(T), T{});
55+ 
56+ auto kernel = [reduce](T *kernelInput, T *kernelOutput, uint32_t inputSize, uint32_t outputSize, uint32_t shape0,
57+ uint32_t shape1) {
58+ RunReduceKernel<T, Pattern>(kernelInput, kernelOutput, inputSize, outputSize, shape0, shape1, reduce);
59+ };
60+ AscendC::SetKernelMode(KernelMode::AIV_MODE);
61+ ICPU_RUN_KF(kernel, 1, inputGm, outputGm, input.size(), outputCount, dim0, dim1);
62+ 
63+ std::vector<T> output(outputGm, outputGm + outputCount);
64+ AscendC::GmFree(inputGm);
65+ AscendC::GmFree(outputGm);
66+ return output;
67+}
68+} // namespace
69+ 
70+TEST(TestApiReduceExtend, ReduceSumFloatArAndRa) {
71+ std::vector<float> arInput(16);
72+ std::iota(arInput.begin(), arInput.end(), 1.0F);
73+ auto arOutput = RunReduce<float, AscendC::Pattern::Reduce::AR>(
74+ arInput, 2, 2, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
75+ AscendC::ReduceSumExtend<float, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, false);
76+ });
77+ EXPECT_EQ(arOutput, (std::vector<float>{36.0F, 100.0F}));
78+ 
79+ std::vector<float> raInput(32);
80+ std::iota(raInput.begin(), raInput.end(), 1.0F);
81+ auto raOutput = RunReduce<float, AscendC::Pattern::Reduce::RA>(
82+ raInput, 8, 4, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
83+ AscendC::ReduceSumExtend<float, AscendC::Pattern::Reduce::RA>(dst, src, tmp, shape, false);
84+ });
85+ for (uint32_t i = 0; i < raOutput.size(); ++i) {
86+ EXPECT_FLOAT_EQ(raOutput[i], 52.0F + 4.0F * i);
87+ }
88+}
89+ 
90+TEST(TestApiReduceExtend, ReduceSumSupportsInt8AndInt16) {
91+ std::vector<int8_t> int8Input(64, 1);
92+ auto int8Output = RunReduce<int8_t, AscendC::Pattern::Reduce::AR>(
93+ int8Input, 2, 2, 32, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
94+ AscendC::ReduceSumExtend<int8_t, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, false);
95+ });
96+ EXPECT_EQ(int8Output, (std::vector<int8_t>{32, 32}));
97+ 
98+ std::vector<int16_t> int16Input(32, 2);
99+ auto int16Output = RunReduce<int16_t, AscendC::Pattern::Reduce::AR>(
100+ int16Input, 2, 2, 16, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
101+ AscendC::ReduceSumExtend<int16_t, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, false);
102+ });
103+ EXPECT_EQ(int16Output, (std::vector<int16_t>{32, 32}));
104+}
105+ 
106+TEST(TestApiReduceExtend, ArithmeticAndLogicalReduceEntries) {
107+ const std::vector<float> input = {1, 2, 3, 4, 5, 6, 7, 8, -1, -2, -3, -4, -5, -6, -7, -8};
108+ 
109+ auto maxOutput = RunReduce<float, AscendC::Pattern::Reduce::AR>(
110+ input, 2, 2, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
111+ AscendC::ReduceMaxExtend<float, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, false);
112+ });
113+ EXPECT_EQ(maxOutput, (std::vector<float>{8.0F, -1.0F}));
114+ 
115+ auto minOutput = RunReduce<float, AscendC::Pattern::Reduce::AR>(
116+ input, 2, 2, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
117+ AscendC::ReduceMinExtend<float, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, false);
118+ });
119+ EXPECT_EQ(minOutput, (std::vector<float>{1.0F, -8.0F}));
120+ 
121+ auto meanOutput = RunReduce<float, AscendC::Pattern::Reduce::AR>(
122+ input, 2, 2, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
123+ AscendC::ReduceMeanExtend<float, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, true);
124+ });
125+ EXPECT_EQ(meanOutput, (std::vector<float>{4.5F, -4.5F}));
126+ 
127+ const std::vector<float> prodInput(16, 1.0F);
128+ auto prodOutput = RunReduce<float, AscendC::Pattern::Reduce::AR>(
129+ prodInput, 2, 2, 8, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
130+ AscendC::ReduceProdExtend<float, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, true);
131+ });
132+ EXPECT_EQ(prodOutput, (std::vector<float>{1.0F, 1.0F}));
133+ 
134+ std::vector<uint8_t> logicalInput(64, 1);
135+ logicalInput[7] = 0;
136+ logicalInput[32] = 0;
137+ auto anyOutput = RunReduce<uint8_t, AscendC::Pattern::Reduce::AR>(
138+ logicalInput, 2, 2, 32, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
139+ AscendC::ReduceAnyExtend<uint8_t, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, true);
140+ });
141+ EXPECT_EQ(anyOutput, (std::vector<uint8_t>{1, 1}));
142+ 
143+ auto allOutput = RunReduce<uint8_t, AscendC::Pattern::Reduce::AR>(
144+ logicalInput, 2, 2, 32, [](auto &dst, auto &src, auto &tmp, const uint32_t *shape) {
145+ AscendC::ReduceAllExtend<uint8_t, AscendC::Pattern::Reduce::AR>(dst, src, tmp, shape, true);
146+ });
147+ EXPECT_EQ(allOutput, (std::vector<uint8_t>{0, 0}));
148+}
@@ -140,7 +140,7 @@ TEST_F(RegReduceApicallTest, RegReduceApi_Test_001) {
140 EXPECT_EQ(status, af::SUCCESS);140 EXPECT_EQ(status, af::SUCCESS);
141 EXPECT_NE(result.find("first_actual"), std::string::npos);141 EXPECT_NE(result.find("first_actual"), std::string::npos);
142 EXPECT_NE(result.find("tmp_reduce_shape"), std::string::npos);142 EXPECT_NE(result.find("tmp_reduce_shape"), std::string::npos);
143- EXPECT_NE(result.find("ReduceMax<"), std::string::npos);143+ EXPECT_NE(result.find("ReduceMaxExtend<"), std::string::npos) << result;
144 EXPECT_NE(result.find("AscendC::Pattern::Reduce::AR"), std::string::npos);144 EXPECT_NE(result.find("AscendC::Pattern::Reduce::AR"), std::string::npos);
145 EXPECT_EQ(result.find("AscirNodeParams"), std::string::npos);145 EXPECT_EQ(result.find("AscirNodeParams"), std::string::npos);
146}146}
@@ -0,0 +1,31 @@
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 "gtest/gtest.h"
12+#include "codegen/ascendc_api_registry.h"
13+ 
14+namespace codegen {
15+TEST(AscendcRegBaseApiRegisterReduceTest, RegistersCompleteReduceExtendSource) {
16+ const auto &source = AscendCApiRegistry::GetInstance().GetFileContent("reduce_extend_reg_base.h");
17+ 
18+ ASSERT_FALSE(source.empty());
19+ EXPECT_NE(source.find("ReduceSumExtend"), std::string::npos);
20+ EXPECT_NE(source.find("ReduceMeanExtend"), std::string::npos);
21+ EXPECT_NE(source.find("ReduceMaxExtend"), std::string::npos);
22+ EXPECT_NE(source.find("ReduceMinExtend"), std::string::npos);
23+ EXPECT_NE(source.find("ReduceProdExtend"), std::string::npos);
24+ EXPECT_NE(source.find("ReduceAnyExtend"), std::string::npos);
25+ EXPECT_NE(source.find("ReduceAllExtend"), std::string::npos);
26+ EXPECT_NE(source.find("ReduceXorSumExtend"), std::string::npos);
27+ EXPECT_NE(source.find("MeanExtend"), std::string::npos);
28+ EXPECT_NE(source.find("SumExtend"), std::string::npos);
29+ EXPECT_EQ(source.find("#include \"reduce/"), std::string::npos);
30+}
31+} // namespace codegen
@@ -32,6 +32,23 @@ set(ascendc_api_regbase_extend_src
32 sign.h32 sign.h
33 signbit.h33 signbit.h
34 reduce_init.h34 reduce_init.h
35+ reduce_extend.h
36+ reduce/reduce_common.h
37+ reduce/reduce_common_util_3510_impl.h
38+ reduce/reduce_common_ar_reuse_align_less_than_vl_3510_impl.h
39+ reduce/reduce_common_ar_reuse_align_3510_impl.h
40+ reduce/reduce_common_ra_reuse_align_3510_impl.h
41+ reduce/reduce_common_ar_ra_reuse_unalign_3510_impl.h
42+ reduce/reduce_sum_3510_impl.h
43+ reduce/reduce_mean_3510_impl.h
44+ reduce/reduce_max_3510_impl.h
45+ reduce/reduce_min_3510_impl.h
46+ reduce/reduce_prod_3510_impl.h
47+ reduce/reduce_any_3510_impl.h
48+ reduce/reduce_all_3510_impl.h
49+ reduce/mean_3510_impl.h
50+ reduce/sum_3510_impl.h
51+ reduce/reduce_xor_sum_3510_impl.h
35 argmax.h52 argmax.h
36 atan2.h53 atan2.h
37 airy_ai.h54 airy_ai.h
@@ -0,0 +1,175 @@
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+/*!
12+ * \file mean_3510_impl.h
13+ * \brief
14+ */
15+ 
16+#ifndef AUTOFUSE_REDUCE_EXTEND_MEAN_C310_IMPL_H
17+#define AUTOFUSE_REDUCE_EXTEND_MEAN_C310_IMPL_H
18+ 
19+#include "kernel_tensor.h"
20+#include "kernel_basic_intf.h"
21+#include "adv_api/reduce/mean_utils.h"
22+#include "reduce/reduce_common.h"
23+ 
24+namespace AscendC {
25+namespace ReduceExtendInternal {
26+namespace Internal {
27+ 
28+template <typename T, typename accType>
29+struct GetConvType {
30+ using type = T;
31+};
32+ 
33+template <>
34+struct GetConvType<half, float> {
35+ using type = float;
36+};
37+ 
38+template <typename T, typename ConvType>
39+__simd_callee__ inline void LoadSrcData(Reg::RegTensor<ConvType> &srcReg, __ubuf__ T *src, uint16_t index,
40+ uint32_t offset, Reg::MaskReg &mask) {
41+ Reg::RegTensor<T> srcTmpReg;
42+ if constexpr (std::is_same<T, half>::value && std::is_same<ConvType, float>::value) {
43+ Reg::LoadAlign<T, Reg::LoadDist::DIST_UNPACK_B16>(srcTmpReg, src + index * offset);
44+ Reg::Cast<float, T, AscendC::Internal::castTraitB16ToB32>(srcReg, srcTmpReg, mask);
45+ } else {
46+ Reg::LoadAlign(srcReg, src + index * offset);
47+ }
48+}
49+ 
50+template <typename T, typename U, typename ConvType>
51+__simd_vf__ inline void MeanForOneRepeatTime(__ubuf__ T *dstUb, __ubuf__ U *srcUb, const MeanParams meanParams,
52+ uint32_t calCount, uint32_t offset) {
53+ uint32_t count;
54+ ConvType scalarValue = static_cast<ConvType>(1.0f / meanParams.n);
55+ Reg::MaskReg mask;
56+ Reg::UnalignReg uregOut;
57+ Reg::RegTensor<ConvType> srcTmpReg, dstTmpReg;
58+ Reg::RegTensor<T> dstReg;
59+ 
60+ for (int i = 0; i < meanParams.outter; i++) {
61+ count = calCount;
62+ mask = Reg::UpdateMask<ConvType>(count);
63+ LoadSrcData(srcTmpReg, srcUb, i, offset, mask);
64+ Reg::ReduceSum(dstTmpReg, srcTmpReg, mask);
65+ Reg::Muls(dstTmpReg, dstTmpReg, scalarValue, mask);
66+ if constexpr (sizeof(T) == sizeof(half) && sizeof(ConvType) == sizeof(float)) {
67+ Reg::Cast<T, float, AscendC::Internal::castTraitB32ToB16>(dstReg, dstTmpReg, mask);
68+ Reg::Pack<uint16_t, uint32_t, Reg::HighLowPart::LOWEST>((Reg::RegTensor<uint16_t> &)dstReg,
69+ (Reg::RegTensor<uint32_t> &)dstReg);
70+ } else {
71+ dstReg = dstTmpReg;
72+ }
73+ Reg::StoreUnAlign<T, Reg::PostLiteral::POST_MODE_UPDATE>(dstUb, dstReg, uregOut, 1);
74+ }
75+ Reg::StoreUnAlignPost(dstUb, uregOut, 0);
76+}
77+ 
78+template <typename T, typename ConvType, bool isFirstRepeat>
79+__simd_vf__ inline void ReduceSumNextN(__ubuf__ ConvType *dstUb, __ubuf__ T *srcUb, const MeanParams meanParams,
80+ uint32_t calCount, uint32_t repeatTimes, uint32_t offset) {
81+ uint32_t count;
82+ Reg::MaskReg mask;
83+ Reg::UnalignReg uregIn;
84+ Reg::RegTensor<ConvType> srcReg, dstReg;
85+ constexpr int32_t eleCountPerVL = GetVecLen() / sizeof(ConvType);
86+ 
87+ for (uint16_t i = 0; i < meanParams.outter; i++) {
88+ count = calCount;
89+ auto dstTmpUb = dstUb + i * offset;
90+ for (uint16_t j = 0; j < repeatTimes; j++) {
91+ mask = Reg::UpdateMask<ConvType>(count);
92+ if constexpr (isFirstRepeat) {
93+ LoadSrcData(srcReg, srcUb + i * meanParams.inner, j, eleCountPerVL, mask);
94+ } else {
95+ LoadSrcData(srcReg, srcUb + i * offset, j, eleCountPerVL, mask);
96+ }
97+ Reg::ReduceSum(dstReg, srcReg, mask);
98+ Reg::StoreUnAlign<ConvType, Reg::PostLiteral::POST_MODE_UPDATE>(dstTmpUb, dstReg, uregIn, 1);
99+ }
100+ Reg::StoreUnAlignPost(dstTmpUb, uregIn, 0);
101+ }
102+ Reg::LocalMemBar<Reg::MemType::VEC_STORE, Reg::MemType::VEC_LOAD>();
103+}
104+} // namespace Internal
105+ 
106+template <typename T, typename accType, bool isReuseSource, bool isBasicBlock, int32_t reduceDim>
107+__aicore__ inline void MeanCheckParams(const LocalTensor<T> &dstTensor, const LocalTensor<T> &srcTensor,
108+ const LocalTensor<uint8_t> &sharedTmpBuffer, const MeanParams &meanParams) {
109+ static_assert(SupportType<T, half, float>(), "current data type is not supported on current device!");
110+ CheckTensorPos<T>(dstTensor, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "Mean");
111+ CheckTensorPos<T>(srcTensor, Hardware::UB, "srcTensor", "VECIN/VECCALC/VECOUT", "Mean");
112+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "Mean");
113+ constexpr uint32_t meanInnerAlignLen = 32;
114+ ASCENDC_ASSERT((1 <= meanParams.n) && (meanParams.n <= meanParams.inner), {
115+ KERNEL_LOG(KERNEL_ERROR, "The value of n must be greater than or equal to 1 and less than or equal to inner.");
116+ });
117+ ASCENDC_ASSERT((meanParams.inner * sizeof(T) % meanInnerAlignLen == 0),
118+ { KERNEL_LOG(KERNEL_ERROR, "The value of inner * sizeof(T) must be an integer multiple of 32."); });
119+}
120+ 
121+template <typename T, typename accType = T, bool isReuseSource = false, bool isBasicBlock = false,
122+ int32_t reduceDim = -1>
123+__aicore__ inline void MeanImpl(const LocalTensor<T> &dstTensor, const LocalTensor<T> &srcTensor,
124+ const LocalTensor<uint8_t> &sharedTmpBuffer, const MeanParams &meanParams) {
125+ // Only for AI Vector Core.
126+ if ASCEND_IS_AIC {
127+ return;
128+ }
129+ 
130+ MeanCheckParams<T, accType, isReuseSource, isBasicBlock, reduceDim>(dstTensor, srcTensor, sharedTmpBuffer,
131+ meanParams);
132+ 
133+ using ConvType = typename Internal::GetConvType<T, accType>::type;
134+ __ubuf__ T *dstUb = (__ubuf__ T *)dstTensor.GetPhyAddr();
135+ __ubuf__ T *srcUb = (__ubuf__ T *)srcTensor.GetPhyAddr();
136+ __ubuf__ ConvType *sharedTmpBufferUb = (__ubuf__ ConvType *)sharedTmpBuffer.GetPhyAddr();
137+ 
138+ constexpr int32_t eleCountPerVL = GetVecLen() / sizeof(ConvType);
139+ uint16_t repeatTimes = CeilDivision(meanParams.n, eleCountPerVL);
140+ uint32_t loopRepeatTimes;
141+ uint32_t calCount = meanParams.n;
142+ 
143+ uint32_t totalCnt = 1;
144+ uint32_t dataSize = repeatTimes;
145+ uint32_t offset = AlignUp(CeilDivision(meanParams.inner, eleCountPerVL), 32);
146+ while (dataSize > 1) {
147+ ++totalCnt;
148+ dataSize = CeilDivision(dataSize, eleCountPerVL);
149+ }
150+ 
151+ if (repeatTimes == 1) {
152+ Internal::MeanForOneRepeatTime<T, T, ConvType>(dstUb, srcUb, meanParams, meanParams.n, meanParams.inner);
153+ return;
154+ }
155+ 
156+ Internal::ReduceSumNextN<T, ConvType, true>(sharedTmpBufferUb, srcUb, meanParams, calCount, repeatTimes, offset);
157+ 
158+ --totalCnt;
159+ loopRepeatTimes = repeatTimes;
160+ while (totalCnt != 0) {
161+ calCount = loopRepeatTimes;
162+ loopRepeatTimes = CeilDivision(loopRepeatTimes, eleCountPerVL);
163+ if (totalCnt == 1) {
164+ Internal::MeanForOneRepeatTime<T, ConvType, ConvType>(dstUb, sharedTmpBufferUb, meanParams, calCount, offset);
165+ } else {
166+ Internal::ReduceSumNextN<ConvType, ConvType, false>(sharedTmpBufferUb, sharedTmpBufferUb, meanParams, calCount,
167+ loopRepeatTimes, offset);
168+ }
169+ --totalCnt;
170+ }
171+}
172+} // namespace ReduceExtendInternal
173+} // namespace AscendC
174+ 
175+#endif // AUTOFUSE_REDUCE_EXTEND_MEAN_C310_IMPL_H
@@ -0,0 +1,71 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_ALL_REDUCE_ALL_C310_IMPL_H_
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_ALL_REDUCE_ALL_C310_IMPL_H_
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#ifdef ASCENDC_CPU_DEBUG
17+#include "reduce/reduce_common_util_3510_impl.h"
18+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
19+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
20+#endif // ASCENDC_CPU_DEBUG
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+ 
26+template <class T, bool isReuseSource = false>
27+__aicore__ inline void ReduceAllARImpl(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr, uint32_t dimA,
28+ uint32_t dimR) {
29+ constexpr uint16_t vlSize = GetVecLen() / sizeof(T);
30+ using CastType = typename ReduceOpInternal::template ExtractReduceCastType<T>::CastT;
31+ 
32+ if (dimR <= vlSize) {
33+ ReduceARReuseSourceLessThanVL<T, Reg::RegTraitNumOne, vlSize,
34+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
35+ Reg::ReduceMin<CastType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<CastType>>>(
36+ dstAddr, srcAddr, dimA, dimR);
37+ } else {
38+ ReduceAROverVLImpl<T, Reg::RegTraitNumOne, vlSize, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
39+ Reg::ReduceMin<CastType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<CastType>>, isReuseSource>(
40+ dstAddr, srcAddr, tmpAddr, dimA, dimR);
41+ }
42+}
43+ 
44+template <typename T, typename pattern, bool isReuseSource = false>
45+__aicore__ inline void ReduceAllImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
46+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
47+ bool srcInnerPad) {
48+ CHECK_FUNC_HIGHLEVEL_API(ReduceAll, (T, pattern), (dst, src, sharedTmpBuffer, srcShape, srcInnerPad, srcShape[1]));
49+ 
50+ CheckTensorPos<T>(dst, Hardware::UB, "dst", "VECIN/VECCALC/VECOUT", "ReduceAll");
51+ CheckTensorPos<T>(src, Hardware::UB, "src", "VECIN/VECCALC/VECOUT", "ReduceAll");
52+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceAll");
53+ static_assert(SupportType<T, uint8_t, float>(), "ReduceAll only support uint8_t/float data type on current device!");
54+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
55+ "ReduceAll only support AR and RA pattern on current device!");
56+ 
57+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
58+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
59+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
60+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
61+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
62+ ReduceAllARImpl<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
63+ } else {
64+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
65+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
66+ }
67+}
68+} // namespace Internal
69+} // namespace ReduceExtendInternal
70+} // namespace AscendC
71+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_All_REDUCE_All_C310_IMPL_H_
@@ -0,0 +1,71 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_ANY_REDUCE_ANY_C310_IMPL_H_
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_ANY_REDUCE_ANY_C310_IMPL_H_
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "reduce/reduce_common_util_3510_impl.h"
17+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
18+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
19+#ifdef ASCENDC_CPU_DEBUG
20+#endif // ASCENDC_CPU_DEBUG
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+ 
26+template <class T, bool isReuseSource = false>
27+__aicore__ inline void ReduceAnyARImpl(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr, uint32_t dimA,
28+ uint32_t dimR) {
29+ constexpr uint16_t vlSize = GetVecLen() / sizeof(T);
30+ using CastType = typename ReduceOpInternal::template ExtractReduceCastType<T>::CastT;
31+ 
32+ if (dimR <= vlSize) {
33+ ReduceARReuseSourceLessThanVL<T, Reg::RegTraitNumOne, vlSize,
34+ Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
35+ Reg::ReduceMax<CastType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<CastType>>>(
36+ dstAddr, srcAddr, dimA, dimR);
37+ } else {
38+ ReduceAROverVLImpl<T, Reg::RegTraitNumOne, vlSize, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
39+ Reg::ReduceMax<CastType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<CastType>>, isReuseSource>(
40+ dstAddr, srcAddr, tmpAddr, dimA, dimR);
41+ }
42+}
43+ 
44+template <typename T, typename pattern, bool isReuseSource = false>
45+__aicore__ inline void ReduceAnyImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
46+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
47+ bool srcInnerPad) {
48+ CHECK_FUNC_HIGHLEVEL_API(ReduceAny, (T, pattern), (dst, src, sharedTmpBuffer, srcShape, srcInnerPad, srcShape[1]));
49+ 
50+ CheckTensorPos<T>(dst, Hardware::UB, "dst", "VECIN/VECCALC/VECOUT", "ReduceAny");
51+ CheckTensorPos<T>(src, Hardware::UB, "src", "VECIN/VECCALC/VECOUT", "ReduceAny");
52+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceAny");
53+ static_assert(SupportType<T, uint8_t, float>(), "ReduceAny only support uint8_t/float data type on current device!");
54+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
55+ "ReduceAny only support AR and RA pattern on current device!");
56+ 
57+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
58+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
59+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
60+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
61+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
62+ ReduceAnyARImpl<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
63+ } else {
64+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
65+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
66+ }
67+}
68+} // namespace Internal
69+} // namespace ReduceExtendInternal
70+} // namespace AscendC
71+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_ANY_REDUCE_ANY_C310_IMPL_H_
@@ -0,0 +1,29 @@
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+// Use the same include guard as adv_api/detail/common/common.h to avoid duplicate CastTrait definitions when UT or ST
12+// includes both headers.
13+#ifndef IMPL_COMMON_COMMON_H
14+#define IMPL_COMMON_COMMON_H
15+ 
16+#include "kernel_basic_intf.h"
17+ 
18+namespace AscendC {
19+namespace Internal {
20+ 
21+constexpr Reg::CastTrait castTraitB16ToB32 = {Reg::RegLayout::ZERO, Reg::SatMode::UNKNOWN, Reg::MaskMergeMode::ZEROING,
22+ RoundMode::UNKNOWN};
23+constexpr Reg::CastTrait castTraitB32ToB16 = {Reg::RegLayout::ZERO, Reg::SatMode::NO_SAT, Reg::MaskMergeMode::ZEROING,
24+ RoundMode::CAST_RINT};
25+ 
26+} // namespace Internal
27+} // namespace AscendC
28+ 
29+#endif // IMPL_COMMON_COMMON_H
@@ -0,0 +1,528 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_AR_REUSE_ALIGN_C310_IMPL_H
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_AR_REUSE_ALIGN_C310_IMPL_H
13+ 
14+#include "kernel_basic_intf.h"
15+#include "kernel_tensor.h"
16+#include "reduce/reduce_common_util_3510_impl.h"
17+#include "reduce/reduce_common_ar_reuse_align_less_than_vl_3510_impl.h"
18+ 
19+namespace AscendC {
20+namespace ReduceExtendInternal {
21+template <class T, class U, const Reg::RegTrait &Trait, const Reg::CastTrait &CastTraitUppper,
22+ const Reg::CastTrait &CastTraitLower, const uint16_t vlSize, auto Binaryfunc, auto Reducefunc>
23+__simd_callee__ inline void ReduceARCastfoldZero(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA, uint32_t dimR,
24+ Reg::MaskReg &fullMask) {
25+ using UnpackSrcT = typename ReduceOpInternal::ExtractUnsignedTypeBySize<sizeof(T)>::T;
26+ using UnpackDstT = typename ReduceOpInternal::ExtractUnsignedTypeBySize<sizeof(U)>::T;
27+ Reg::RegTensor<U, Trait> vreg0CastB32;
28+ Reg::RegTensor<U, Trait> vreg1CastB32;
29+ Reg::RegTensor<T, Trait> vreg0;
30+ Reg::RegTensor<T, Trait> vreg1;
31+ Reg::UnalignReg uDst;
32+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
33+ Reg::LoadAlign(vreg0, srcAddr + loopA * dimR);
34+ Reg::LoadAlign(vreg1, srcAddr + vlSize / 2 + loopA * dimR);
35+ Binaryfunc(vreg0, vreg0, vreg1, fullMask);
36+ Reg::UnPack((Reg::RegTensor<UnpackDstT, Trait> &)vreg0, (Reg::RegTensor<UnpackSrcT, Trait> &)vreg0);
37+ Reg::Cast<U, T, ReduceOpInternal::CastTraitBF16F32>(vreg0CastB32, vreg0, fullMask);
38+ Reducefunc(vreg1CastB32, vreg0CastB32, fullMask);
39+ Reg::Cast<T, U, ReduceOpInternal::CastTraitF32BF16>(vreg1, vreg1CastB32, fullMask);
40+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, 1);
41+ }
42+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, 0);
43+}
44+ 
45+template <class T, const Reg::RegTrait &Trait, auto Binaryfunc, auto Reducefunc>
46+__simd_callee__ inline void ReduceARfoldOneToThree(Reg::RegTensor<T, Trait> &vreg0, Reg::RegTensor<T, Trait> &vreg2,
47+ Reg::MaskReg &fullMask) {
48+ if constexpr (IsSameType<T, bfloat16_t>::value) {
49+ ReduceOpInternal::ReduceARCastfoldOneToThree<T, float, Trait, ReduceOpInternal::CastTraitBF16F32,
50+ ReduceOpInternal::CastTraitF32BF16, Binaryfunc, Reducefunc>(
51+ vreg0, vreg2, fullMask);
52+ } else if constexpr (SupportBytes<T, 1>()) {
53+ ReduceOpInternal::ReduceARCastfoldOneToThree<T, half, Trait, ReduceOpInternal::CastTraitB8F16,
54+ ReduceOpInternal::CastTraitF16B8, Binaryfunc, Reducefunc>(vreg0, vreg2,
55+ fullMask);
56+ } else {
57+ Reducefunc(vreg2, vreg0, fullMask);
58+ }
59+}
60+ 
61+template <class T, const Reg::RegTrait &Trait, const uint16_t vlSize, auto Binaryfunc, auto Reducefunc,
62+ bool isReuseSource>
63+__simd_vf__ inline void ReduceARB64OverVLVF(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
64+ uint32_t dimA, uint32_t dimR, uint32_t mainR, uint32_t tailR,
65+ uint16_t dimRAxis, uint16_t inplaceRepeats, uint32_t inplaceTail,
66+ uint16_t needInplaceAdd, uint16_t copyRepeats, uint16_t base,
67+ uint16_t folds, uint16_t avgFolds, uint16_t mainTimes, uint16_t foldZero,
68+ uint16_t foldOne, uint16_t foldTwo) {
69+ __ubuf__ T *addr;
70+ Reg::MaskReg mask;
71+ Reg::MaskReg fullMask;
72+ fullMask = Reg::CreateMask<T, Reg::MaskPattern::ALL, Trait>();
73+ // Process mainR and tailR
74+ if constexpr (isReuseSource) {
75+ addr = srcAddr;
76+ Reg::RegTensor<T, Trait> b64VregMain;
77+ Reg::RegTensor<T, Trait> b64VregTail;
78+ for (uint16_t i = 0; i < needInplaceAdd; i++) {
79+ uint32_t sreg0 = tailR;
80+ for (uint16_t loopR = 0; loopR < inplaceRepeats; loopR++) {
81+ mask = Reg::UpdateMask<T, Trait>(sreg0);
82+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
83+ Reg::LoadAlign(b64VregMain, srcAddr + loopA * dimRAxis + loopR * vlSize);
84+ Reg::LoadAlign(b64VregTail, srcAddr + loopA * dimRAxis + mainR + loopR * vlSize);
85+ Binaryfunc(b64VregMain, b64VregMain, b64VregTail, mask);
86+ Reg::StoreAlign(addr + loopA * dimRAxis + loopR * vlSize, b64VregMain, mask);
87+ }
88+ }
89+ Reg::LocalMemBar<Reg::MemType::VEC_STORE, Reg::MemType::VEC_LOAD>();
90+ }
91+ } else {
92+ addr = tmpAddr;
93+ uint16_t dimRTmp = mainR;
94+ Reg::RegTensor<T, Trait> b64VregMain;
95+ Reg::RegTensor<T, Trait> b64VregTail;
96+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
97+ // do inplace add tail with main
98+ for (uint16_t loopR = 0; loopR < inplaceRepeats; loopR++) {
99+ Reg::LoadAlign(b64VregMain, srcAddr + loopA * dimRAxis + loopR * vlSize);
100+ Reg::LoadAlign(b64VregTail, srcAddr + loopA * dimRAxis + mainR + loopR * vlSize);
@@ -0,0 +1,172 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_AR_REUSE_ALIGN_LESS_THAN_VL_C310_IMPL_H
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_AR_REUSE_ALIGN_LESS_THAN_VL_C310_IMPL_H
13+ 
14+#include "kernel_basic_intf.h"
15+#include "kernel_tensor.h"
16+#include "reduce/reduce_common_util_3510_impl.h"
17+ 
18+namespace AscendC {
19+namespace ReduceExtendInternal {
20+template <class T, class U, const Reg::RegTrait &Trait, const Reg::CastTrait &CastTraitUppper,
21+ const Reg::CastTrait &CastTraitLower, const uint16_t vlSize, auto Binaryfunc, auto Reducefunc>
22+__simd_vf__ inline void ReduceARCastLessThanVL(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA, uint32_t dimR) {
23+ if (dimR <= (vlSize / 2)) {
24+ Reg::RegTensor<T, Trait> vreg0;
25+ Reg::RegTensor<T, Trait> vreg1;
26+ Reg::RegTensor<U, Trait> vreg0CastUpper;
27+ Reg::RegTensor<U, Trait> vreg1CastUpper;
28+ Reg::UnalignReg uDst;
29+ uint32_t sreg1 = dimR;
30+ Reg::MaskReg mask = Reg::UpdateMask<U>(sreg1);
31+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
32+ if constexpr (IsSameType<T, bfloat16_t>::value) {
33+ Reg::LoadAlign<T, Reg::LoadDist::DIST_US_B16>(vreg0, srcAddr + loopA * dimR);
34+ } else {
35+ Reg::LoadAlign<T, Reg::LoadDist::DIST_US_B8>(vreg0, srcAddr + loopA * dimR);
36+ }
37+ Reg::Cast<U, T, CastTraitUppper>(vreg0CastUpper, vreg0, mask);
38+ Reducefunc(vreg1CastUpper, vreg0CastUpper, mask);
39+ Reg::Cast<T, U, CastTraitLower>(vreg1, vreg1CastUpper, mask);
40+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, 1);
41+ }
42+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, 0);
43+ } else {
44+ Reg::RegTensor<T, Trait> vreg0;
45+ Reg::RegTensor<T, Trait> vreg1;
46+ Reg::RegTensor<T, Trait> vreg2;
47+ Reg::RegTensor<U, Trait> vreg0CastB32;
48+ Reg::RegTensor<U, Trait> vreg1CastB32;
49+ Reg::UnalignReg uDst;
50+ uint32_t sreg1 = dimR;
51+ Reg::MaskReg fullMask = Reg::CreateMask<T, Reg::MaskPattern::ALL, Trait>();
52+ Reg::MaskReg mask = Reg::UpdateMask<U>(sreg1);
53+ mask = Reg::UpdateMask<U>(sreg1);
54+ Reg::MaskPack(mask, mask);
55+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
56+ Reg::LoadAlign(vreg0, srcAddr + loopA * dimR);
57+ Reg::LoadAlign(vreg1, srcAddr + vlSize / 2 + loopA * dimR);
58+ Binaryfunc(vreg2, vreg0, vreg1, mask);
59+ Select(vreg2, vreg2, vreg0, mask);
60+ if constexpr (IsSameType<T, bfloat16_t>::value) {
61+ Reg::UnPack((Reg::RegTensor<uint32_t, Trait> &)vreg2, (Reg::RegTensor<uint16_t, Trait> &)vreg2);
62+ } else {
63+ Reg::UnPack((Reg::RegTensor<uint16_t, Trait> &)vreg2, (Reg::RegTensor<uint8_t, Trait> &)vreg2);
64+ }
65+ Reg::Cast<U, T, CastTraitUppper>(vreg0CastB32, vreg2, fullMask);
66+ Reducefunc(vreg1CastB32, vreg0CastB32, fullMask);
67+ Reg::Cast<T, U, CastTraitLower>(vreg1, vreg1CastB32, fullMask);
68+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, 1);
69+ }
70+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, 0);
71+ }
72+}
73+ 
74+template <class T, const Reg::RegTrait &Trait, auto Reducefunc>
75+__simd_vf__ inline void ReduceARLessThanVL(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA, uint32_t dimR) {
76+ Reg::RegTensor<T, Trait> vreg0;
77+ Reg::RegTensor<T, Trait> vreg1;
78+ Reg::UnalignReg uDst;
79+ uint32_t sreg1 = dimR;
80+ Reg::MaskReg mask = Reg::UpdateMask<T, Trait>(sreg1);
81+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
82+ Reg::LoadAlign(vreg0, srcAddr + loopA * dimR);
83+ Reducefunc(vreg1, vreg0, mask);
84+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, 1);
85+ }
86+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, 0);
87+}
88+ 
89+template <class T, const Reg::RegTrait &Trait, ReduceType reduceType>
90+__simd_callee__ inline void GroupReduce(Reg::RegTensor<T, Trait> &dst, Reg::RegTensor<T, Trait> &src,
91+ Reg::MaskReg &mask) {
92+ if constexpr (reduceType == ReduceType::SUM) {
93+ Reg::ReduceSumWithDataBlock(dst, src, mask);
94+ } else if constexpr (reduceType == ReduceType::MAX) {
95+ Reg::ReduceMaxWithDataBlock(dst, src, mask);
96+ } else if constexpr (reduceType == ReduceType::MIN) {
97+ Reg::ReduceMinWithDataBlock(dst, src, mask);
98+ }
99+}
100+ 
101+template <class T, const Reg::RegTrait &Trait, const uint16_t vlSize, auto Binaryfunc, auto GroupReduceType,
102+ bool NeedFoldR = true>
103+__simd_vf__ inline void GroupReduceVf(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint16_t innerFoldNum, uint16_t fusedA,
104+ uint16_t strideA, uint32_t outerRepElement) {
105+ constexpr uint16_t blockDataLen = GetDataBlockSizeInBytes() / sizeof(T);
106+ constexpr uint16_t blockNumInVl = vlSize / blockDataLen;
107+ Reg::RegTensor<T, Trait> vreg0;
108+ Reg::RegTensor<T, Trait> vreg1;
109+ Reg::UnalignReg uDst;
110+ Reg::MaskReg mask;
111+ const uint16_t innerFoldBinaryNum = innerFoldNum - 1;
112+ 
113+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(fusedA); ++loopA) {
114+ mask = Reg::UpdateMask<T, Trait>(outerRepElement);
115+ if constexpr (NeedFoldR) {
116+ auto srcAddrFold = srcAddr + blockDataLen;
117+ Reg::LoadAlign<T, Reg::DataCopyMode::DATA_BLOCK_COPY, Reg::PostLiteral::POST_MODE_UPDATE>(
118+ vreg0, srcAddr, innerFoldNum, strideA, mask);
119+ for (uint16_t loopR = 0; loopR < innerFoldBinaryNum; ++loopR) {
120+ Reg::LoadAlign<T, Reg::DataCopyMode::DATA_BLOCK_COPY, Reg::PostLiteral::POST_MODE_UPDATE>(
121+ vreg1, srcAddrFold, innerFoldNum, 1, mask);
122+ Binaryfunc(vreg0, vreg1, vreg0, mask);
123+ }
124+ } else {
125+ Reg::LoadAlign(vreg0, srcAddr + vlSize * loopA);
126+ }
127+ GroupReduce<T, Trait, GroupReduceType>(vreg1, vreg0, mask);
128+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, blockNumInVl);
129+ }
130+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, blockNumInVl);
131+}
132+ 
133+template <class T, const Reg::RegTrait &Trait, const uint16_t vlSize, auto Binaryfunc, auto groupReduceType,
134+ bool NeedFoldR = true>
135+__aicore__ inline void GroupReduceARLessThanVL(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA, uint32_t dimR) {
136+ constexpr uint16_t blockDataLen = GetDataBlockSizeInBytes() / sizeof(T);
137+ constexpr uint16_t blockNumInVl = vlSize / blockDataLen;
138+ const auto innerFoldNum = dimR / blockDataLen;
139+ const auto fusedA = CeilDivision(dimA, blockNumInVl);
140+ const auto strideA = (blockNumInVl * dimR) / blockDataLen;
141+ uint32_t outerRepElement = dimA * blockDataLen;
142+ GroupReduceVf<T, Trait, vlSize, Binaryfunc, groupReduceType, NeedFoldR>(dstAddr, srcAddr, innerFoldNum, fusedA,
143+ strideA, outerRepElement);
144+}
145+ 
146+template <class T, const Reg::RegTrait &Trait, const uint16_t vlSize, auto Binaryfunc, auto Reducefunc,
147+ ReduceType groupReduceType = ReduceType::NONE>
148+__aicore__ inline void ReduceARReuseSourceLessThanVL(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA,
149+ uint32_t dimR) {
150+ if (dimR == 1) {
151+ ReduceOpInternal::ReduceCopyOutImpl<T>(dstAddr, srcAddr, dimA);
152+ } else if constexpr (IsSameType<T, bfloat16_t>::value) {
153+ ReduceARCastLessThanVL<T, float, Trait, ReduceOpInternal::CastTraitBF16F32, ReduceOpInternal::CastTraitF32BF16,
154+ vlSize, Binaryfunc, Reducefunc>(dstAddr, srcAddr, dimA, dimR);
155+ } else if constexpr (SupportBytes<T, 1>()) {
156+ ReduceARCastLessThanVL<T, half, Trait, ReduceOpInternal::CastTraitB8F16, ReduceOpInternal::CastTraitF16B8, vlSize,
157+ Binaryfunc, Reducefunc>(dstAddr, srcAddr, dimA, dimR);
158+ } else if constexpr (groupReduceType != ReduceType::NONE) {
159+ if (dimR == GetDataBlockSizeInBytes() / sizeof(T)) {
160+ GroupReduceARLessThanVL<T, Trait, vlSize, Binaryfunc, groupReduceType, false>(dstAddr, srcAddr, dimA, dimR);
161+ } else if (dimR < vlSize / 2) {
162+ GroupReduceARLessThanVL<T, Trait, vlSize, Binaryfunc, groupReduceType, true>(dstAddr, srcAddr, dimA, dimR);
163+ } else {
164+ ReduceARLessThanVL<T, Trait, Reducefunc>(dstAddr, srcAddr, dimA, dimR);
165+ }
166+ } else {
167+ ReduceARLessThanVL<T, Trait, Reducefunc>(dstAddr, srcAddr, dimA, dimR);
168+ }
169+}
170+} // namespace ReduceExtendInternal
171+} // namespace AscendC
172+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_AR_REUSE_ALIGN_LESS_THAN_VL_C310_IMPL_H
@@ -0,0 +1,149 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_UTIL_C310_IMPL_H
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_UTIL_C310_IMPL_H
13+ 
14+#include "kernel_basic_intf.h"
15+#include "kernel_tensor.h"
16+ 
17+namespace AscendC {
18+namespace ReduceExtendInternal {
19+namespace ReduceOpInternal {
20+// Calculate the sum of two points based on count. The main block size is ex.2000->1024 900->512.
21+__aicore__ inline uint32_t CalculateRMainBlock(uint32_t count) {
22+ constexpr int32_t TWO_BITS = 2;
23+ constexpr int32_t FOUR_BITS = 4;
24+ constexpr int32_t EIGHT_BITS = 8;
25+ constexpr int32_t SIXTEEN_BITS = 16;
26+ count |= count >> 1;
27+ count |= count >> TWO_BITS;
28+ count |= count >> FOUR_BITS;
29+ count |= count >> EIGHT_BITS;
30+ count |= count >> SIXTEEN_BITS;
31+ return (count + 1) >> 1;
32+}
33+ 
34+constexpr uint16_t BASE_FOLD = 4;
35+constexpr uint16_t BASE_FOLD_B64 = 3;
36+constexpr uint16_t FOLD_THREE = 3;
37+constexpr uint16_t FOLD_TWO = 2;
38+constexpr uint16_t FOLD_ONE = 1;
39+constexpr uint32_t U16_STRIDE = 65535;
40+constexpr uint16_t REGULAR_FOLD_NUM = 2;
41+constexpr uint16_t NO_REUSE_FOLD_NUM = 2;
42+ 
43+static constexpr Reg::CastTrait CastTraitBF16F32 = {Reg::RegLayout::ZERO, Reg::SatMode::UNKNOWN,
44+ Reg::MaskMergeMode::ZEROING};
45+static constexpr Reg::CastTrait CastTraitF32BF16 = {Reg::RegLayout::ZERO, Reg::SatMode::NO_SAT,
46+ Reg::MaskMergeMode::ZEROING, RoundMode::CAST_RINT};
47+static constexpr Reg::CastTrait CastTraitB8F16 = {Reg::RegLayout::ZERO, Reg::SatMode::UNKNOWN,
48+ Reg::MaskMergeMode::ZEROING, RoundMode::CAST_RINT};
49+static constexpr Reg::CastTrait CastTraitF16B8 = {Reg::RegLayout::ZERO, Reg::SatMode::NO_SAT,
50+ Reg::MaskMergeMode::ZEROING, RoundMode::CAST_RINT};
51+ 
52+__aicore__ inline uint32_t CalculateMainR(int64_t dimR, bool isAR, uint16_t vlSize) {
53+ constexpr uint16_t MAX_OFFSET = 16;
54+ int64_t mainR = 1;
55+ for (uint16_t i = 1; i < MAX_OFFSET; i++) {
56+ if ((dimR >> i) == 0) {
57+ break;
58+ }
59+ mainR = 1 << i;
60+ }
61+ 
62+ if (isAR && dimR < vlSize) {
63+ mainR = dimR;
64+ }
65+ return static_cast<uint32_t>(mainR);
66+}
67+ 
68+__aicore__ inline uint16_t CalculateFolds(const uint16_t count) {
69+ constexpr uint16_t MAX_OFFSET = 16;
70+ uint16_t folds = 0;
71+ uint16_t base = count;
72+ for (uint16_t i = 1; i < MAX_OFFSET; i++) {
73+ if ((base >> i) == 0) {
74+ break;
75+ }
76+ folds++;
77+ }
78+ return folds;
79+}
80+ 
81+template <class T, class U, const Reg::RegTrait &Trait, const Reg::CastTrait &CastTraitUppper,
82+ const Reg::CastTrait &CastTraitLower, auto Binaryfunc, auto Reducefunc>
83+__simd_callee__ inline void ReduceARCastfoldOneToThree(Reg::RegTensor<T, Trait> &vreg0, Reg::RegTensor<T, Trait> &vreg1,
84+ Reg::MaskReg &fullMask) {
85+ Reg::RegTensor<U, Trait> vreg0CastB32;
86+ Reg::RegTensor<U, Trait> vreg1CastB32;
87+ Reg::RegTensor<T, Trait> vreg2;
88+ Reg::RegTensor<T, Trait> vreg3;
89+ Reg::RegTensor<T, Trait> vreg4;
90+ Duplicate(vreg4, static_cast<T>(0), fullMask);
91+ Interleave(vreg2, vreg3, vreg0, vreg4);
92+ Binaryfunc(vreg0, vreg2, vreg3, fullMask);
93+ Reg::Cast<U, T, CastTraitUppper>(vreg0CastB32, vreg0, fullMask);
94+ Reducefunc(vreg1CastB32, vreg0CastB32, fullMask);
95+ Reg::Cast<T, U, CastTraitLower>(vreg1, vreg1CastB32, fullMask);
96+}
97+ 
98+template <class T>
99+__simd_vf__ inline void ReduceCopyOutImpl(__ubuf__ T *dst, __ubuf__ T *src, const uint32_t calCount) {
100+ uint16_t repeatElm = GetVecLen();
101+ uint32_t sreg = calCount * sizeof(T);
102+ uint16_t repeatTime = static_cast<uint16_t>(CeilDivision(sreg, repeatElm));
103+ Reg::MaskReg preg;
104+ Reg::RegTensor<uint8_t> srcReg;
105+ for (uint16_t i = 0; i < repeatTime; ++i) {
106+ preg = Reg::UpdateMask<uint8_t>(sreg);
107+ Reg::LoadAlign(srcReg, (__ubuf__ uint8_t *)src + i * repeatElm);
108+ Reg::StoreAlign((__ubuf__ uint8_t *)dst + i * repeatElm, srcReg, preg);
109+ }
110+}
111+ 
112+template <typename T>
113+struct ExtractReduceCastType {
114+ using CastT = T;
115+};
116+ 
117+template <>
118+struct ExtractReduceCastType<bfloat16_t> {
119+ using CastT = float;
120+};
121+ 
122+template <>
123+struct ExtractReduceCastType<uint8_t> {
124+ using CastT = half;
125+};
126+ 
127+template <>
128+struct ExtractReduceCastType<int8_t> {
129+ using CastT = half;
130+};
131+ 
132+template <uint32_t size = sizeof(uint8_t)>
133+struct ExtractUnsignedTypeBySize {
134+ using T = uint8_t;
135+};
136+ 
137+template <>
138+struct ExtractUnsignedTypeBySize<sizeof(uint16_t)> {
139+ using T = uint16_t;
140+};
141+ 
142+template <>
143+struct ExtractUnsignedTypeBySize<sizeof(uint32_t)> {
144+ using T = uint32_t;
145+};
146+} // namespace ReduceOpInternal
147+} // namespace ReduceExtendInternal
148+} // namespace AscendC
149+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_COMMON_UTIL_C310_IMPL_H
@@ -0,0 +1,131 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_MAX_REDUCE_MAX_C310_IMPL_H_
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_MAX_REDUCE_MAX_C310_IMPL_H_
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "kernel_tiling/kernel_tiling.h"
17+#include "reduce/reduce_common_util_3510_impl.h"
18+#include "reduce/reduce_common_ar_ra_reuse_unalign_3510_impl.h"
19+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
20+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+template <class T, bool isReuseSource = false>
26+__aicore__ inline void ReduceMaxARB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
27+ const uint32_t srcShape[]) {
28+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
29+ ReduceARImpl<T, Reg::RegTraitNumTwo,
30+ Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
31+ Reg::ReduceMax<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>, isReuseSource>(
32+ dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
33+ } else {
34+ ReduceARReuseSourceUnAligned<
35+ T, Reg::RegTraitNumTwo, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
36+ Reg::ReduceMax<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(
37+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
38+ }
39+}
40+ 
41+template <class T, bool isReuseSource = false>
42+__aicore__ inline void ReduceMaxARReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
43+ const uint32_t srcShape[]) {
44+ using castType = typename ReduceOpInternal::ExtractReduceCastType<T>::CastT;
45+ if ((srcShape[1] * sizeof(T)) % 32 == 0 || srcShape[1] == 1) {
46+ ReduceARImpl<T, Reg::RegTraitNumOne, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
47+ Reg::ReduceMax<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>, isReuseSource,
48+ ReduceType::MAX>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
49+ } else {
50+ if constexpr (SupportBytes<T, 1>()) {
51+ constexpr uint32_t ONE_STRIDE = 32768;
52+ uint16_t repeatTimes = (srcShape[0] + ONE_STRIDE - 1) >> 15;
53+ for (uint16_t i = 0; i < repeatTimes; ++i) {
54+ uint32_t dimA = ONE_STRIDE < srcShape[0] - ONE_STRIDE * i ? ONE_STRIDE : srcShape[0] - ONE_STRIDE * i;
55+ ReduceARReuseSourceUnAligned<T, Reg::RegTraitNumOne,
56+ Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
57+ Reg::ReduceMax<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>>(
58+ dstAddr + ONE_STRIDE * i, srcAddr + ONE_STRIDE * i * srcShape[1], dimA, srcShape[1]);
59+ }
60+ } else {
61+ ReduceARReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
62+ Reg::ReduceMax<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>>(
63+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
64+ }
65+ }
66+}
67+ 
68+template <class T, bool isReuseSource = false>
69+__aicore__ inline void ReduceMaxRAB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
70+ const uint32_t srcShape[]) {
71+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
72+ ReduceRAB64ReuseSource<T, Reg::RegTraitNumTwo,
73+ Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
74+ isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
75+ } else {
76+ ReduceRAReuseSourceUnAlignedB64<T, Reg::RegTraitNumTwo,
77+ Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(
78+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
79+ }
80+}
81+ 
82+template <class T, bool isReuseSource = false>
83+__aicore__ inline void ReduceMaxRAReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
84+ const uint32_t srcShape[]) {
85+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
86+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
87+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
88+ } else {
89+ ReduceRAReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Max<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>>(
90+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
91+ }
92+}
93+ 
94+template <class T, class pattern, bool isReuseSource = false>
95+__aicore__ inline void ReduceMaxImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
96+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
97+ bool srcInnerPad) {
98+ CheckTensorPos<T>(dst, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "ReduceMax");
99+ CheckTensorPos<T>(src, Hardware::UB, "srcTensor", "VECIN/VECCALC/VECOUT", "ReduceMax");
100+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceMax");
101+ static_assert(
102+ SupportType<T, int8_t, uint8_t, int16_t, uint16_t, half, bfloat16_t, int32_t, uint32_t, float, int64_t,
103+ uint64_t>(),
104+ "ReduceMax only support "
105+ "int8_t/uint8_t/int16_t/uint16_t/half/bfloat16_t/int32_t/uint32_t/float/int64_t/uint64_t data type on current "
106+ "device!");
107+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
108+ "ReduceMax only support AR and RA pattern on current device!");
109+ 
110+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
111+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
112+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
113+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
114+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
115+ if constexpr (SupportBytes<T, 8>()) {
116+ ReduceMaxARB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
117+ } else {
118+ ReduceMaxARReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
119+ }
120+ } else {
121+ if constexpr (SupportBytes<T, 8>()) {
122+ ReduceMaxRAB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
123+ } else {
124+ ReduceMaxRAReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
125+ }
126+ }
127+}
128+} // namespace Internal
129+} // namespace ReduceExtendInternal
130+} // namespace AscendC
131+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_MAX_REDUCE_MAX_C310_IMPL_H_
@@ -0,0 +1,54 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_MEAN_REDUCE_MEAN_C310_IMPL_H
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_MEAN_REDUCE_MEAN_C310_IMPL_H
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "kernel_tiling/kernel_tiling.h"
17+#include "reduce/reduce_common_util_3510_impl.h"
18+#ifdef ASCENDC_CPU_DEBUG
19+#endif // ASCENDC_CPU_DEBUG
20+ 
21+namespace AscendC {
22+namespace ReduceExtendInternal {
23+namespace Internal {
24+template <class T, class pattern, bool isReuseSource = false>
25+__aicore__ inline void ReduceMeanImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
26+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
27+ bool srcInnerPad) {
28+ CHECK_FUNC_HIGHLEVEL_API(ReduceMean, (T, pattern), (dst, src, sharedTmpBuffer, srcShape, srcInnerPad, srcShape[1]));
29+ 
30+ CheckTensorPos<T>(dst, Hardware::UB, "dst", "VECIN/VECCALC/VECOUT", "ReduceMean");
31+ CheckTensorPos<T>(src, Hardware::UB, "src", "VECIN/VECCALC/VECOUT", "ReduceMean");
32+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceMean");
33+ static_assert(SupportType<T, float>(), "ReduceMean only support float data type on current device!");
34+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
35+ "ReduceMean only support AR and RA pattern on current device!");
36+ 
37+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
38+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
39+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
40+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
41+ 
42+ ReduceSumImpl<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape, srcInnerPad);
43+ if constexpr (IsSameType<pattern, Pattern::Reduce::AR>::value) {
44+ float lastAxisValReciprocal = 1.0f / static_cast<int32_t>(srcShape[1]);
45+ Muls<T>(dst, dst, lastAxisValReciprocal, srcShape[0]);
46+ } else if constexpr (IsSameType<pattern, Pattern::Reduce::RA>::value) {
47+ float firstAxisValReciprocal = 1.0f / static_cast<int32_t>(srcShape[0]);
48+ Muls<T>(dst, dst, firstAxisValReciprocal, srcShape[1]);
49+ }
50+}
51+} // namespace Internal
52+} // namespace ReduceExtendInternal
53+} // namespace AscendC
54+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_MEAN_REDUCE_MEAN_C310_IMPL_H
@@ -0,0 +1,137 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_MIN_REDUCE_MIN_C310_IMPL_H_
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_MIN_REDUCE_MIN_C310_IMPL_H_
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "kernel_tiling/kernel_tiling.h"
17+#include "reduce/reduce_common_util_3510_impl.h"
18+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
19+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
20+#include "reduce/reduce_common_ar_ra_reuse_unalign_3510_impl.h"
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+template <class T, bool isReuseSource = false>
26+__aicore__ inline void ReduceMinARB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
27+ const uint32_t srcShape[]) {
28+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
29+ ReduceARImpl<T, Reg::RegTraitNumTwo,
30+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
31+ Reg::ReduceMin<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>, isReuseSource>(
32+ dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
33+ } else {
34+ ReduceARReuseSourceUnAligned<
35+ T, Reg::RegTraitNumTwo, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
36+ Reg::ReduceMin<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(
37+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
38+ }
39+}
40+ 
41+template <class T, bool isReuseSource = false>
42+__aicore__ inline void ReduceMinARReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
43+ const uint32_t srcShape[]) {
44+ using castType = typename ReduceOpInternal::ExtractReduceCastType<T>::CastT;
45+ if ((srcShape[1] * sizeof(T)) % 32 == 0 || srcShape[1] == 1) {
46+ ReduceARImpl<T, Reg::RegTraitNumOne, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
47+ Reg::ReduceMin<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>, isReuseSource,
48+ ReduceType::MIN>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
49+ } else {
50+ if constexpr (SupportBytes<T, 1>()) {
51+ constexpr uint32_t ONE_STRIDE = 32768;
52+ uint16_t repeatTimes = (srcShape[0] + ONE_STRIDE - 1) >> 15;
53+ for (uint16_t i = 0; i < repeatTimes; ++i) {
54+ uint32_t dimA = ONE_STRIDE < srcShape[0] - ONE_STRIDE * i ? ONE_STRIDE : srcShape[0] - ONE_STRIDE * i;
55+ ReduceARReuseSourceUnAligned<T, Reg::RegTraitNumOne,
56+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
57+ Reg::ReduceMin<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>>(
58+ dstAddr + ONE_STRIDE * i, srcAddr + ONE_STRIDE * i * srcShape[1], dimA, srcShape[1]);
59+ }
60+ } else {
61+ ReduceARReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
62+ Reg::ReduceMin<castType, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<castType>>>(
63+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
64+ }
65+ }
66+}
67+ 
68+template <class T, bool isReuseSource = false>
69+__aicore__ inline void ReduceMinRAB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
70+ const uint32_t srcShape[]) {
71+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
72+ if (srcShape[1] * sizeof(T) <= GetVecLen() / 2) {
73+ ReduceRAConcatImpl<T, Reg::RegTraitNumTwo,
74+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
75+ isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
76+ } else {
77+ ReduceRAB64ReuseSource<T, Reg::RegTraitNumTwo,
78+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
79+ isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
80+ }
81+ } else {
82+ ReduceRAReuseSourceUnAlignedB64<T, Reg::RegTraitNumTwo,
83+ Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(
84+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
85+ }
86+}
87+ 
88+template <class T, bool isReuseSource = false>
89+__aicore__ inline void ReduceMinRAReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
90+ const uint32_t srcShape[]) {
91+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
92+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
93+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
94+ } else {
95+ ReduceRAReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Min<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>>(
96+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
97+ }
98+}
99+ 
100+template <class T, class pattern, bool isReuseSource = false>
101+__aicore__ inline void ReduceMinImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
102+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
103+ bool srcInnerPad) {
104+ CheckTensorPos<T>(dst, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "ReduceMin");
105+ CheckTensorPos<T>(src, Hardware::UB, "srcTensor", "VECIN/VECCALC/VECOUT", "ReduceMin");
106+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceMin");
107+ static_assert(
108+ SupportType<T, int8_t, uint8_t, int16_t, uint16_t, half, bfloat16_t, int32_t, uint32_t, float, int64_t,
109+ uint64_t>(),
110+ "ReduceMin only support "
111+ "int8_t/uint8_t/int16_t/uint16_t/half/bfloat16_t/int32_t/uint32_t/float/int64_t/uint64_t data type on current "
112+ "device!");
113+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
114+ "ReduceMin only support AR and RA pattern on current device!");
115+ 
116+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
117+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
118+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
119+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
120+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
121+ if constexpr (SupportBytes<T, 8>()) {
122+ ReduceMinARB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
123+ } else {
124+ ReduceMinARReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
125+ }
126+ } else {
127+ if constexpr (SupportBytes<T, 8>()) {
128+ ReduceMinRAB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
129+ } else {
130+ ReduceMinRAReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
131+ }
132+ }
133+}
134+} // namespace Internal
135+} // namespace ReduceExtendInternal
136+} // namespace AscendC
137+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_MIN_REDUCE_MIN_C310_IMPL_H_
@@ -0,0 +1,137 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_PROD_REDUCE_PROD_C310_IMPL_H_
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_PROD_REDUCE_PROD_C310_IMPL_H_
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "reduce/reduce_common_util_3510_impl.h"
17+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
18+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
19+#ifdef ASCENDC_CPU_DEBUG
20+#endif // ASCENDC_CPU_DEBUG
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+template <typename T>
26+__aicore__ inline void ReduceProd(Reg::RegTensor<T> &dst, Reg::RegTensor<T> src, Reg::MaskReg mask) {
27+ Reg::RegTensor<T> tempOne;
28+ // mask invalid data in src to one
29+ Reg::Duplicate(tempOne, 1);
30+ Reg::Select(src, src, tempOne, mask);
31+ 
32+ if constexpr (sizeof(T) == 1) {
33+ // fold to 128
34+ Reg::DeInterleave(dst, src, src, tempOne);
35+ Reg::Mul(src, dst, src, mask);
36+ }
37+ if constexpr (sizeof(T) <= 2) {
38+ // fold to 64
39+ Reg::DeInterleave(dst, src, src, tempOne);
40+ Reg::Mul(src, dst, src, mask);
41+ }
42+ // fold from 64 to 2
43+ Reg::DeInterleave(dst, src, src, tempOne);
44+ Reg::Mul(src, dst, src, mask);
45+ Reg::DeInterleave(dst, src, src, tempOne);
46+ Reg::Mul(src, dst, src, mask);
47+ Reg::DeInterleave(dst, src, src, tempOne);
48+ Reg::Mul(src, dst, src, mask);
49+ Reg::DeInterleave(dst, src, src, tempOne);
50+ Reg::Mul(src, dst, src, mask);
51+ Reg::DeInterleave(dst, src, src, tempOne);
52+ Reg::Mul(src, dst, src, mask);
53+ // fold to 1
54+ Reg::DeInterleave(dst, src, src, tempOne);
55+ Reg::Mul(dst, dst, src, mask);
56+}
57+ 
58+template <class T, const Reg::RegTrait &Trait, const uint16_t vlSize>
59+__simd_vf__ inline void ReduceProdARLessThanVLVF(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, uint32_t dimA, uint32_t dimR,
60+ const uint16_t repeatTime) {
61+ Reg::RegTensor<T, Trait> vreg0;
62+ Reg::RegTensor<T, Trait> vreg1;
63+ Reg::UnalignReg uDst;
64+ Reg::RegTensor<T> tempOne;
65+ // mask invalid data in src to one
66+ Reg::Duplicate(tempOne, 1);
67+ uint32_t sreg1 = dimR;
68+ Reg::MaskReg mask = Reg::UpdateMask<T, Trait>(sreg1);
69+ for (uint16_t loopA = 0; loopA < static_cast<uint16_t>(dimA); loopA++) {
70+ Reg::LoadAlign(vreg0, srcAddr + loopA * dimR);
71+ Reg::Select(vreg0, vreg0, tempOne, mask);
72+ if constexpr (sizeof(T) == 1) {
73+ // fold to 128
74+ Reg::DeInterleave(vreg1, vreg0, vreg0, tempOne);
75+ Reg::Mul(vreg0, vreg1, vreg0, mask);
76+ }
77+ if constexpr (sizeof(T) <= 2) {
78+ // fold to 64
79+ Reg::DeInterleave(vreg1, vreg0, vreg0, tempOne);
80+ Reg::Mul(vreg0, vreg1, vreg0, mask);
81+ }
82+ for (uint16_t i = 0; i < repeatTime; ++i) {
83+ Reg::DeInterleave(vreg1, vreg0, vreg0, tempOne);
84+ Reg::Mul(vreg0, vreg1, vreg0, mask);
85+ }
86+ // fold to 1
87+ Reg::DeInterleave(vreg1, vreg0, vreg0, tempOne);
88+ Reg::Mul(vreg1, vreg1, vreg0, mask);
89+ Reg::StoreUnAlign((__ubuf__ T *&)dstAddr, vreg1, uDst, 1);
90+ }
91+ Reg::StoreUnAlignPost((__ubuf__ T *&)dstAddr, uDst, 0);
92+}
93+ 
94+template <class T, bool isReuseSource = false>
95+__aicore__ inline void ReduceProdARImpl(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr, uint32_t dimA,
96+ uint32_t dimR) {
97+ constexpr uint16_t vlSize = GetVecLen() / sizeof(T);
98+ if (dimR == 1) {
99+ ReduceOpInternal::ReduceCopyOutImpl<T>(dstAddr, srcAddr, dimA);
100+ } else if (dimR <= vlSize) {
101+ uint16_t repeatTime = AscendC::Internal::FindClosestPowerOfTwo(dimR);
102+ repeatTime = (1 << repeatTime) < dimR ? repeatTime : repeatTime - 1;
103+ ReduceProdARLessThanVLVF<T, Reg::RegTraitNumOne, vlSize>(dstAddr, srcAddr, dimA, dimR, repeatTime);
104+ } else {
105+ ReduceAROverVLImpl<T, Reg::RegTraitNumOne, vlSize, Reg::Mul<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
106+ ReduceProd<T>, isReuseSource>(dstAddr, srcAddr, tmpAddr, dimA, dimR);
107+ }
108+}
109+ 
110+template <typename T, typename pattern, bool isReuseSource = false>
111+__aicore__ inline void ReduceProdImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
112+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
113+ bool srcInnerPad) {
114+ CHECK_FUNC_HIGHLEVEL_API(ReduceProd, (T, pattern), (dst, src, sharedTmpBuffer, srcShape, srcInnerPad, srcShape[1]));
115+ 
116+ CheckTensorPos<T>(dst, Hardware::UB, "dst", "VECIN/VECCALC/VECOUT", "ReduceProd");
117+ CheckTensorPos<T>(src, Hardware::UB, "src", "VECIN/VECCALC/VECOUT", "ReduceProd");
118+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceProd");
119+ static_assert(SupportType<T, float>(), "ReduceProd only support float data type on current device!");
120+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
121+ "ReduceProd only support AR and RA pattern on current device!");
122+ 
123+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
124+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
125+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
126+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
127+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
128+ ReduceProdARImpl<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
129+ } else {
130+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Mul<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
131+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
132+ }
133+}
134+} // namespace Internal
135+} // namespace ReduceExtendInternal
136+} // namespace AscendC
137+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_PROD_REDUCE_PROD_C310_IMPL_H_
@@ -0,0 +1,204 @@
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+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_SUM_REDUCE_SUM_C310_IMPL_H
12+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_SUM_REDUCE_SUM_C310_IMPL_H
13+ 
14+#include "kernel_tensor.h"
15+#include "kernel_basic_intf.h"
16+#include "kernel_tiling/kernel_tiling.h"
17+#include "reduce/reduce_common_util_3510_impl.h"
18+#include "reduce/reduce_common_ar_ra_reuse_unalign_3510_impl.h"
19+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
20+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace Internal {
25+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
26+template <const Reg::RegTrait &Trait>
27+__simd_callee__ inline void ReduceSumInt16(Reg::RegTensor<int16_t, Trait> &dst, Reg::RegTensor<int16_t, Trait> src,
28+ Reg::MaskReg mask) {
29+ Reg::RegTensor<int32_t, Trait> sum;
30+ Reg::ReduceSum<int32_t, int16_t, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<int32_t, Trait>,
31+ Reg::RegTensor<int16_t, Trait>>(sum, src, mask);
32+ Reg::Pack<uint16_t, int32_t, Reg::HighLowPart::LOWEST>((Reg::RegTensor<uint16_t, Trait> &)dst, sum);
33+}
34+#endif
35+ 
36+template <class T, bool isReuseSource = false>
37+__aicore__ inline void ReduceSumARB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
38+ const uint32_t srcShape[]) {
39+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
40+ ReduceARImpl<T, Reg::RegTraitNumTwo,
41+ Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
42+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>,
43+ Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
44+ isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
45+ } else {
46+ ReduceARReuseSourceUnAligned<
47+ T, Reg::RegTraitNumTwo, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
48+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>,
49+ Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(dstAddr, srcAddr, srcShape[0], srcShape[1]);
50+ }
51+}
52+ 
53+template <class T, bool isReuseSource = false>
54+__aicore__ inline void ReduceSumARReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
55+ const uint32_t srcShape[]) {
56+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
57+ if constexpr (std::is_same_v<T, int16_t>) {
58+ if ((srcShape[1] * sizeof(T)) % 32 == 0 || srcShape[1] == 1) {
59+ ReduceARImpl<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
60+ ReduceSumInt16<Reg::RegTraitNumOne>, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[0],
61+ srcShape[1]);
62+ } else {
63+ ReduceARReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
64+ ReduceSumInt16<Reg::RegTraitNumOne>>(dstAddr, srcAddr, srcShape[0], srcShape[1]);
65+ }
66+ } else {
67+ if ((srcShape[1] * sizeof(T)) % 32 == 0 || srcShape[1] == 1) {
68+ ReduceARImpl<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
69+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>, Reg::RegTensor<T>>,
70+ isReuseSource, ReduceType::SUM>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
71+ } else {
72+ ReduceARReuseSourceUnAligned<
73+ T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
74+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>, Reg::RegTensor<T>>>(
75+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
76+ }
77+ }
78+#else
79+ if ((srcShape[1] * sizeof(T)) % 32 == 0 || srcShape[1] == 1) {
80+ ReduceARImpl<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
81+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>, Reg::RegTensor<T>>, isReuseSource,
82+ ReduceType::SUM>(dstAddr, srcAddr, tmpAddr, srcShape[0], srcShape[1]);
83+ } else {
84+ ReduceARReuseSourceUnAligned<
85+ T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>,
86+ Reg::ReduceSum<T, T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>, Reg::RegTensor<T>>>(
87+ dstAddr, srcAddr, srcShape[0], srcShape[1]);
88+ }
89+#endif
90+}
91+ 
92+template <class T, bool isReuseSource = false>
93+__aicore__ inline void ReduceSumRAB64ReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
94+ const uint32_t srcShape[]) {
95+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
96+ ReduceRAB64ReuseSource<T, Reg::RegTraitNumTwo,
97+ Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>,
98+ isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
99+ } else {
100+ ReduceRAReuseSourceUnAlignedB64<T, Reg::RegTraitNumTwo,
101+ Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T, Reg::RegTraitNumTwo>>>(
102+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
103+ }
104+}
105+ 
106+template <class T, bool isReuseSource = false>
107+__aicore__ inline void ReduceSumRAReuseSourceCompute(__ubuf__ T *dstAddr, __ubuf__ T *srcAddr, __ubuf__ T *tmpAddr,
108+ const uint32_t srcShape[]) {
109+ if ((srcShape[1] * sizeof(T)) % 32 == 0) {
110+ ReduceRAImpl<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>, isReuseSource>(
111+ dstAddr, srcAddr, tmpAddr, srcShape[1], srcShape[0]);
112+ } else {
113+ ReduceRAReuseSourceUnAligned<T, Reg::RegTraitNumOne, Reg::Add<T, Reg::MaskMergeMode::ZEROING, Reg::RegTensor<T>>>(
114+ dstAddr, srcAddr, srcShape[1], srcShape[0]);
115+ }
116+}
117+ 
118+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
119+__simd_vf__ inline void NarrowReduceSumOutput(__ubuf__ int8_t *dstAddr, __ubuf__ int16_t *srcAddr, uint32_t count) {
120+ constexpr uint32_t elementsPerLoop = GetVecLen() / sizeof(int16_t);
121+ const uint32_t loops = CeilDivision(count, elementsPerLoop);
122+ uint32_t remaining = count;
123+ Reg::RegTensor<int16_t> srcReg;
124+ Reg::RegTensor<int8_t> dstReg;
125+ Reg::MaskReg mask;
126+ for (uint32_t i = 0; i < loops; ++i) {
127+ mask = Reg::UpdateMask<int16_t>(remaining);
128+ Reg::LoadAlign(srcReg, srcAddr + i * elementsPerLoop);
129+ Reg::Pack<uint8_t, uint16_t, Reg::HighLowPart::LOWEST>((Reg::RegTensor<uint8_t> &)dstReg,
130+ (Reg::RegTensor<uint16_t> &)srcReg);
131+ Reg::MaskPack(mask, mask);
132+ Reg::StoreAlign(dstAddr + i * elementsPerLoop, dstReg, mask);
133+ }
134+}
135+ 
136+template <class pattern>
137+__aicore__ inline void ReduceSumInt8Compute(const LocalTensor<int8_t> &dst, const LocalTensor<int8_t> &src,
138+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[]) {
139+ constexpr uint32_t blockBytes = 32;
140+ const uint32_t inputCount = srcShape[0] * srcShape[1];
141+ const uint32_t outputCount = std::is_same_v<pattern, Pattern::Reduce::AR> ? srcShape[0] : srcShape[1];
142+ const uint32_t widenedInputBytes = CeilDivision(inputCount * sizeof(int16_t), blockBytes) * blockBytes;
143+ LocalTensor<int16_t> widenedSrcTensor = sharedTmpBuffer.ReinterpretCast<int16_t>();
144+ LocalTensor<int16_t> widenedDstTensor = widenedSrcTensor[widenedInputBytes / sizeof(int16_t)];
145+ Cast(widenedSrcTensor, src, RoundMode::CAST_NONE, inputCount);
146+ PipeBarrier<PIPE_V>();
147+ __ubuf__ int16_t *widenedSrc = (__ubuf__ int16_t *)widenedSrcTensor.GetPhyAddr();
148+ __ubuf__ int16_t *widenedDst = (__ubuf__ int16_t *)widenedDstTensor.GetPhyAddr();
149+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
150+ ReduceSumARReuseSourceCompute<int16_t, true>(widenedDst, widenedSrc, widenedDst, srcShape);
151+ } else {
152+ ReduceSumRAReuseSourceCompute<int16_t, true>(widenedDst, widenedSrc, widenedDst, srcShape);
153+ }
154+ PipeBarrier<PIPE_V>();
155+ NarrowReduceSumOutput((__ubuf__ int8_t *)dst.GetPhyAddr(), widenedDst, outputCount);
156+}
157+#endif
158+ 
159+template <class T, class pattern, bool isReuseSource = false>
160+__aicore__ inline void ReduceSumImpl(const LocalTensor<T> &dst, const LocalTensor<T> &src,
161+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
162+ bool srcInnerPad) {
163+ CheckTensorPos<T>(dst, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "ReduceSum");
164+ CheckTensorPos<T>(src, Hardware::UB, "srcTensor", "VECIN/VECCALC/VECOUT", "ReduceSum");
165+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceSum");
166+ static_assert(std::is_same_v<pattern, Pattern::Reduce::AR> || std::is_same_v<pattern, Pattern::Reduce::RA>,
167+ "ReduceSum only support AR and RA pattern on current device!");
168+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
169+ static_assert(SupportType<T, int8_t, int16_t, int32_t, uint32_t, float, int64_t, uint64_t>(),
170+ "ReduceSum only support int8_t/int16_t/int32_t/uint32_t/float/int64_t/uint64_t data type on current "
171+ "device!");
172+#else
173+ static_assert(SupportType<T, int32_t, uint32_t, float, int64_t, uint64_t>(),
174+ "ReduceSum only support int32_t/uint32_t/float/int64_t/uint64_t data type on current device!");
175+#endif
176+ __ubuf__ T *dstAddr = (__ubuf__ T *)dst.GetPhyAddr();
177+ __ubuf__ T *srcAddr = (__ubuf__ T *)src.GetPhyAddr();
178+ LocalTensor<T> tmpBuf = sharedTmpBuffer.ReinterpretCast<T>();
179+ __ubuf__ T *tmpAddr = (__ubuf__ T *)tmpBuf.GetPhyAddr();
180+#if defined(__NPU_ARCH__) && (__NPU_ARCH__ == 3510)
181+ if constexpr (std::is_same_v<T, int8_t>) {
182+ ReduceSumInt8Compute<pattern>(dst, src, sharedTmpBuffer, srcShape);
183+ } else
184+#endif
185+ {
186+ if constexpr (std::is_same_v<pattern, Pattern::Reduce::AR>) {
187+ if constexpr (SupportBytes<T, 8>()) {
188+ ReduceSumARB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
189+ } else {
190+ ReduceSumARReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
191+ }
192+ } else {
193+ if constexpr (SupportBytes<T, 8>()) {
194+ ReduceSumRAB64ReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
195+ } else {
196+ ReduceSumRAReuseSourceCompute<T, isReuseSource>(dstAddr, srcAddr, tmpAddr, srcShape);
197+ }
198+ }
199+ }
200+}
201+} // namespace Internal
202+} // namespace ReduceExtendInternal
203+} // namespace AscendC
204+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_SUM_REDUCE_SUM_C310_IMPL_H
@@ -0,0 +1,98 @@
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+/*!
12+ * \file reduce_xor_sum_3510_impl.h
13+ * \brief
14+ */
15+ 
16+#ifndef AUTOFUSE_REDUCE_EXTEND_REDUCE_XOR_SUM_C310_IMPL_H
17+#define AUTOFUSE_REDUCE_EXTEND_REDUCE_XOR_SUM_C310_IMPL_H
18+#include "kernel_tensor.h"
19+#include "kernel_basic_intf.h"
20+#include "kernel_tiling/kernel_tiling.h"
21+ 
22+namespace AscendC {
23+namespace ReduceExtendInternal {
24+namespace ReduceXorSumAPI {
25+ 
26+constexpr Reg::CastTrait castTraitF16F32 = {Reg::RegLayout::ZERO, Reg::SatMode::UNKNOWN, Reg::MaskMergeMode::ZEROING,
27+ RoundMode::UNKNOWN};
28+constexpr Reg::CastTrait castTraitF32F16 = {Reg::RegLayout::ZERO, Reg::SatMode::SAT, Reg::MaskMergeMode::ZEROING,
29+ RoundMode::CAST_RINT};
30+ 
31+template <typename T>
32+__simd_callee__ inline void LoadSrcDataAndXor(Reg::RegTensor<float> &srcReg, __ubuf__ T *src0, __ubuf__ T *src1,
33+ uint16_t index, Reg::MaskReg &mask) {
34+ constexpr uint16_t eleCountPerVL = GetVecLen() / sizeof(float);
35+ Reg::RegTensor<T> src0TmpReg, src1TmpReg;
36+ Reg::LoadAlign<T, Reg::LoadDist::DIST_UNPACK_B16>(src0TmpReg, src0 + index * eleCountPerVL);
37+ Reg::LoadAlign<T, Reg::LoadDist::DIST_UNPACK_B16>(src1TmpReg, src1 + index * eleCountPerVL);
38+ Reg::Xor(src0TmpReg, src0TmpReg, src1TmpReg, mask);
39+ Reg::Cast<float, T, castTraitF16F32>(srcReg, src0TmpReg, mask);
40+}
41+ 
42+template <typename T>
43+__simd_vf__ inline void ReduceXorSumCoreImpl(__ubuf__ T *dstUb, __ubuf__ T *src0Ub, __ubuf__ T *src1Ub,
44+ uint32_t calCount) {
45+ Reg::MaskReg mask;
46+ Reg::UnalignReg ureg;
47+ Reg::RegTensor<T> dstReg;
48+ Reg::RegTensor<float> srcTmpReg, dstTmpReg, tmpReg, zeroReg;
49+ Reg::MaskReg fullMask = Reg::CreateMask<float>();
50+ constexpr int32_t eleCountPerVL = GetVecLen() / sizeof(float);
51+ uint16_t repeatTimes = CeilDivision(calCount, eleCountPerVL);
52+ Reg::Duplicate(zeroReg, 0, fullMask);
53+ for (uint16_t i = 0; i < repeatTimes; i++) {
54+ mask = Reg::UpdateMask<float>(calCount);
55+ LoadSrcDataAndXor(srcTmpReg, src0Ub, src1Ub, i, mask);
56+ Reg::ReduceSum(dstTmpReg, srcTmpReg, mask);
57+ Reg::Add(zeroReg, zeroReg, dstTmpReg, mask);
58+ }
59+ Reg::Cast<T, float, castTraitF32F16>(dstReg, zeroReg, fullMask);
60+ Reg::Pack<uint16_t, uint32_t, Reg::HighLowPart::LOWEST>((Reg::RegTensor<uint16_t> &)dstReg,
61+ (Reg::RegTensor<uint32_t> &)dstReg);
62+ Reg::StoreUnAlign(dstUb, dstReg, ureg, 1);
63+ Reg::StoreUnAlignPost(dstUb, ureg, 0);
64+}
65+} // namespace ReduceXorSumAPI
66+ 
67+template <typename T, bool isReuseSource = false>
68+__aicore__ inline void ReduceXorSumCheckParams(LocalTensor<T> &dstTensor, const LocalTensor<T> &src0Tensor,
69+ const LocalTensor<T> &src1Tensor, LocalTensor<uint8_t> &sharedTmpBuffer,
70+ const uint32_t calCount) {
71+ static_assert(std::is_same<T, int16_t>::value, "ReduceXorSum only support int16_t data type on current device!");
72+ CheckTensorPos<T>(dstTensor, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "ReduceXorSum");
73+ CheckTensorPos<T>(src0Tensor, Hardware::UB, "src0Tensor", "VECIN/VECCALC/VECOUT", "ReduceXorSum");
74+ CheckTensorPos<T>(src1Tensor, Hardware::UB, "src1Tensor", "VECIN/VECCALC/VECOUT", "ReduceXorSum");
75+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "ReduceXorSum");
76+ CheckCalCount(calCount, "calCount", src0Tensor, "src0Tensor", "ReduceXorSum");
77+ CheckCalCount(calCount, "calCount", src1Tensor, "src1Tensor", "ReduceXorSum");
78+}
79+ 
80+template <typename T, bool isReuseSource = false>
81+__aicore__ inline void ReduceXorSumCompute(LocalTensor<T> &dstTensor, const LocalTensor<T> &src0Tensor,
82+ const LocalTensor<T> &src1Tensor, LocalTensor<uint8_t> &sharedTmpBuffer,
83+ const uint32_t calCount) {
84+ // Only for AI Vector Core.
85+ if ASCEND_IS_AIC {
86+ return;
87+ }
88+ 
89+ ReduceXorSumCheckParams<T, isReuseSource>(dstTensor, src0Tensor, src1Tensor, sharedTmpBuffer, calCount);
90+ __ubuf__ T *dstUb = (__ubuf__ T *)dstTensor.GetPhyAddr();
91+ __ubuf__ T *src0Ub = (__ubuf__ T *)src0Tensor.GetPhyAddr();
92+ __ubuf__ T *src1Ub = (__ubuf__ T *)src1Tensor.GetPhyAddr();
93+ ReduceXorSumAPI::ReduceXorSumCoreImpl<T>(dstUb, src0Ub, src1Ub, calCount);
94+}
95+} // namespace ReduceExtendInternal
96+} // namespace AscendC
97+ 
98+#endif // AUTOFUSE_REDUCE_EXTEND_REDUCE_XOR_SUM_C310_IMPL_H
@@ -0,0 +1,136 @@
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+/*!
12+ * \file sum_3510_impl.h
13+ * \brief
14+ */
15+ 
16+#ifndef AUTOFUSE_REDUCE_EXTEND_SUM_C310_IMPL_H
17+#define AUTOFUSE_REDUCE_EXTEND_SUM_C310_IMPL_H
18+ 
19+#include "kernel_basic_intf.h"
20+#include "kernel_tensor.h"
21+#include "adv_api/reduce/sum_utils.h"
22+ 
23+namespace AscendC {
24+namespace ReduceExtendInternal {
25+namespace SumInternal {
26+template <typename T>
27+__simd_vf__ inline void SumForOneRepeatTime(__ubuf__ T *dstUb, __ubuf__ T *srcUb, const SumParams sumParams,
28+ uint32_t count, uint32_t offset) {
29+ uint32_t calCount;
30+ Reg::MaskReg mask;
31+ Reg::UnalignReg uregOut;
32+ Reg::RegTensor<T> srcReg, dstReg;
33+ 
34+ for (int i = 0; i < sumParams.outter; i++) {
35+ calCount = count;
36+ mask = Reg::UpdateMask<T>(calCount);
37+ Reg::LoadAlign(srcReg, srcUb + i * offset);
38+ Reg::ReduceSum(dstReg, srcReg, mask);
39+ Reg::StoreUnAlign<T, Reg::PostLiteral::POST_MODE_UPDATE>(dstUb, dstReg, uregOut, 1);
40+ }
41+ Reg::StoreUnAlignPost(dstUb, uregOut, 0);
42+}
43+ 
44+template <typename T, bool isFirstRepeat>
45+__simd_vf__ inline void ReduceSumNextN(__ubuf__ T *dstUb, __ubuf__ T *srcUb, const SumParams sumParams,
46+ uint32_t calCount, uint32_t repeatTimes, uint32_t offset) {
47+ uint32_t count;
48+ Reg::MaskReg mask;
49+ Reg::UnalignReg uregIn;
50+ Reg::RegTensor<T> srcReg, dstReg;
51+ constexpr int32_t eleCountPerVL = GetVecLen() / sizeof(T);
52+ for (uint16_t i = 0; i < sumParams.outter; i++) {
53+ count = calCount;
54+ auto dstTmpUb = dstUb + i * offset;
55+ for (uint16_t j = 0; j < repeatTimes; j++) {
56+ mask = Reg::UpdateMask<T>(count);
57+ if constexpr (isFirstRepeat) {
58+ Reg::LoadAlign(srcReg, srcUb + i * sumParams.inner + j * eleCountPerVL);
59+ } else {
60+ Reg::LoadAlign(srcReg, srcUb + i * offset + j * eleCountPerVL);
61+ }
62+ Reg::ReduceSum(dstReg, srcReg, mask);
63+ Reg::StoreUnAlign<T, Reg::PostLiteral::POST_MODE_UPDATE>(dstTmpUb, dstReg, uregIn, 1);
64+ }
65+ Reg::StoreUnAlignPost(dstTmpUb, uregIn, 0);
66+ }
67+ Reg::LocalMemBar<Reg::MemType::VEC_STORE, Reg::MemType::VEC_LOAD>();
68+}
69+} // namespace SumInternal
70+ 
71+template <typename T, int32_t reduceDim = -1, bool isReuseSource = false, bool isBasicBlock = false>
72+__aicore__ inline void SumCheckParams(const LocalTensor<T> &dstTensor, const LocalTensor<T> &srcTensor,
73+ const LocalTensor<uint8_t> &sharedTmpBuffer, const SumParams &sumParams) {
74+ static_assert(SupportType<T, half, float>(), "current data type is not supported on current device!");
75+ CheckTensorPos<T>(dstTensor, Hardware::UB, "dstTensor", "VECIN/VECCALC/VECOUT", "Sum");
76+ CheckTensorPos<T>(srcTensor, Hardware::UB, "srcTensor", "VECIN/VECCALC/VECOUT", "Sum");
77+ CheckTensorPos<uint8_t>(sharedTmpBuffer, Hardware::UB, "sharedTmpBuffer", "VECIN/VECCALC/VECOUT", "Sum");
78+ constexpr uint32_t sumInnerAlignLen = 32;
79+ ASCENDC_ASSERT((1 <= sumParams.n) && (sumParams.n <= sumParams.inner), {
80+ KERNEL_LOG(KERNEL_ERROR, "The value of n must be greater than or equal to 1 and less than or equal to inner.");
81+ });
82+ ASCENDC_ASSERT((sumParams.inner * sizeof(T) % sumInnerAlignLen == 0),
83+ { KERNEL_LOG(KERNEL_ERROR, "The value of inner * sizeof(T) must be an integer multiple of 32."); });
84+}
85+ 
86+template <typename T, int32_t reduceDim = -1, bool isReuseSource = false, bool isBasicBlock = false>
87+__aicore__ inline void SumCompute(const LocalTensor<T> &dstTensor, const LocalTensor<T> &srcTensor,
88+ const LocalTensor<uint8_t> &sharedTmpBuffer, const SumParams &sumParams) {
89+ // Only for AI Vector Core.
90+ if ASCEND_IS_AIC {
91+ return;
92+ }
93+ 
94+ SumCheckParams<T, reduceDim, isReuseSource, isBasicBlock>(dstTensor, srcTensor, sharedTmpBuffer, sumParams);
95+ __ubuf__ T *dstUb = (__ubuf__ T *)dstTensor.GetPhyAddr();
96+ __ubuf__ T *srcUb = (__ubuf__ T *)srcTensor.GetPhyAddr();
97+ __ubuf__ T *sharedTmpBufferUb = (__ubuf__ T *)sharedTmpBuffer.GetPhyAddr();
98+ 
99+ constexpr int32_t eleCountPerVL = GetVecLen() / sizeof(T);
100+ uint16_t repeatTimes = CeilDivision(sumParams.n, eleCountPerVL);
101+ uint32_t loopRepeatTimes;
102+ uint32_t calCount = sumParams.n;
103+ 
104+ uint32_t totalCnt = 1;
105+ uint32_t dataSize = repeatTimes;
106+ uint32_t offset = AlignUp(CeilDivision(sumParams.inner, eleCountPerVL), 32);
107+ while (dataSize > 1) {
108+ ++totalCnt;
109+ dataSize = CeilDivision(dataSize, eleCountPerVL);
110+ }
111+ 
112+ if (repeatTimes == 1) {
113+ SumInternal::SumForOneRepeatTime<T>(dstUb, srcUb, sumParams, sumParams.n, sumParams.inner);
114+ return;
115+ }
116+ 
117+ SumInternal::ReduceSumNextN<T, true>(sharedTmpBufferUb, srcUb, sumParams, calCount, repeatTimes, offset);
118+ 
119+ --totalCnt;
120+ loopRepeatTimes = repeatTimes;
121+ while (totalCnt != 0) {
122+ calCount = loopRepeatTimes;
123+ loopRepeatTimes = CeilDivision(loopRepeatTimes, eleCountPerVL);
124+ if (totalCnt == 1) {
125+ SumInternal::SumForOneRepeatTime<T>(dstUb, sharedTmpBufferUb, sumParams, calCount, offset);
126+ } else {
127+ SumInternal::ReduceSumNextN<T, false>(sharedTmpBufferUb, sharedTmpBufferUb, sumParams, calCount, loopRepeatTimes,
128+ offset);
129+ }
130+ --totalCnt;
131+ }
132+}
133+} // namespace ReduceExtendInternal
134+} // namespace AscendC
135+ 
136+#endif // AUTOFUSE_REDUCE_EXTEND_SUM_C310_IMPL_H
@@ -0,0 +1,148 @@
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 AUTOFUSE_V35_ASCENDC_API_REGBASE_REDUCE_EXTEND_H
12+#define AUTOFUSE_V35_ASCENDC_API_REGBASE_REDUCE_EXTEND_H
13+ 
14+#include "adv_api/reduce/reduce.h"
15+ 
16+#include "reduce/reduce_common_util_3510_impl.h"
17+#include "reduce/reduce_common_ar_reuse_align_less_than_vl_3510_impl.h"
18+#include "reduce/reduce_common_ar_reuse_align_3510_impl.h"
19+#include "reduce/reduce_common_ra_reuse_align_3510_impl.h"
20+#include "reduce/reduce_common_ar_ra_reuse_unalign_3510_impl.h"
21+#include "reduce/reduce_sum_3510_impl.h"
22+#include "reduce/reduce_mean_3510_impl.h"
23+#include "reduce/reduce_max_3510_impl.h"
24+#include "reduce/reduce_min_3510_impl.h"
25+#include "reduce/reduce_prod_3510_impl.h"
26+#include "reduce/reduce_any_3510_impl.h"
27+#include "reduce/reduce_all_3510_impl.h"
28+#include "reduce/mean_3510_impl.h"
29+#include "reduce/sum_3510_impl.h"
30+#include "reduce/reduce_xor_sum_3510_impl.h"
31+ 
32+namespace AscendC {
33+template <class T, class pattern, bool isReuseSource = false>
34+__aicore__ inline void ReduceSumExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src,
35+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
36+ bool srcInnerPad) {
37+ if ASCEND_IS_AIC {
38+ return;
39+ }
40+ ReduceExtendInternal::Internal::ReduceSumImpl<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape,
41+ srcInnerPad);
42+}
43+ 
44+template <class T, class pattern, bool isReuseSource = false>
45+__aicore__ inline void ReduceSumExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src, const uint32_t srcShape[],
46+ bool srcInnerPad) {
47+ LocalTensor<uint8_t> sharedTmpBuffer;
48+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer);
49+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); });
50+ ReduceSumExtend<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape, srcInnerPad);
51+}
52+ 
53+template <class T, class pattern, bool isReuseSource = false>
54+__aicore__ inline void ReduceMeanExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src,
55+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[],
56+ bool srcInnerPad) {
57+ if ASCEND_IS_AIC {
58+ return;
59+ }
60+ ReduceExtendInternal::Internal::ReduceMeanImpl<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape,
61+ srcInnerPad);
62+}
63+ 
64+template <class T, class pattern, bool isReuseSource = false>
65+__aicore__ inline void ReduceMeanExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src, const uint32_t srcShape[],
66+ bool srcInnerPad) {
67+ LocalTensor<uint8_t> sharedTmpBuffer;
68+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer);
69+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); });
70+ ReduceMeanExtend<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape, srcInnerPad);
71+}
72+ 
73+#define AUTOFUSE_DEFINE_REDUCE_EXTEND(apiName, implName) \
74+ template <class T, class pattern, bool isReuseSource = false> \
75+ __aicore__ inline void apiName(const LocalTensor<T> &dst, const LocalTensor<T> &src, \
76+ const LocalTensor<uint8_t> &sharedTmpBuffer, const uint32_t srcShape[], \
77+ bool srcInnerPad) { \
78+ if ASCEND_IS_AIC { \
79+ return; \
80+ } \
81+ ReduceExtendInternal::Internal::implName##Impl<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape, \
82+ srcInnerPad); \
83+ } \
84+ template <class T, class pattern, bool isReuseSource = false> \
85+ __aicore__ inline void apiName(const LocalTensor<T> &dst, const LocalTensor<T> &src, const uint32_t srcShape[], \
86+ bool srcInnerPad) { \
87+ LocalTensor<uint8_t> sharedTmpBuffer; \
88+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer); \
89+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); }); \
90+ apiName<T, pattern, isReuseSource>(dst, src, sharedTmpBuffer, srcShape, srcInnerPad); \
91+ }
92+ 
93+AUTOFUSE_DEFINE_REDUCE_EXTEND(ReduceMaxExtend, ReduceMax)
94+AUTOFUSE_DEFINE_REDUCE_EXTEND(ReduceMinExtend, ReduceMin)
95+AUTOFUSE_DEFINE_REDUCE_EXTEND(ReduceProdExtend, ReduceProd)
96+AUTOFUSE_DEFINE_REDUCE_EXTEND(ReduceAnyExtend, ReduceAny)
97+AUTOFUSE_DEFINE_REDUCE_EXTEND(ReduceAllExtend, ReduceAll)
98+ 
99+#undef AUTOFUSE_DEFINE_REDUCE_EXTEND
100+ 
101+template <typename T, typename accType = T, bool isReuseSource = false, bool isBasicBlock = false,
102+ int32_t reduceDim = -1>
103+__aicore__ inline void MeanExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src,
104+ const LocalTensor<uint8_t> &sharedTmpBuffer, const MeanParams &meanParams) {
105+ ReduceExtendInternal::MeanImpl<T, accType, isReuseSource, isBasicBlock, reduceDim>(dst, src, sharedTmpBuffer,
106+ meanParams);
107+}
108+ 
109+template <typename T, typename accType = T, bool isReuseSource = false, bool isBasicBlock = false,
110+ int32_t reduceDim = -1>
111+__aicore__ inline void MeanExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src, const MeanParams &meanParams) {
112+ LocalTensor<uint8_t> sharedTmpBuffer;
113+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer);
114+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); });
115+ MeanExtend<T, accType, isReuseSource, isBasicBlock, reduceDim>(dst, src, sharedTmpBuffer, meanParams);
116+}
117+ 
118+template <typename T, int32_t reduceDim = -1, bool isReuseSource = false, bool isBasicBlock = false>
119+__aicore__ inline void SumExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src,
120+ const LocalTensor<uint8_t> &sharedTmpBuffer, const SumParams &sumParams) {
121+ ReduceExtendInternal::SumCompute<T, reduceDim, isReuseSource, isBasicBlock>(dst, src, sharedTmpBuffer, sumParams);
122+}
123+ 
124+template <typename T, int32_t reduceDim = -1, bool isReuseSource = false, bool isBasicBlock = false>
125+__aicore__ inline void SumExtend(const LocalTensor<T> &dst, const LocalTensor<T> &src, const SumParams &sumParams) {
126+ LocalTensor<uint8_t> sharedTmpBuffer;
127+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer);
128+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); });
129+ SumExtend<T, reduceDim, isReuseSource, isBasicBlock>(dst, src, sharedTmpBuffer, sumParams);
130+}
131+ 
132+template <typename T, bool isReuseSource = false>
133+__aicore__ inline void ReduceXorSumExtend(LocalTensor<T> &dst, const LocalTensor<T> &src0, const LocalTensor<T> &src1,
134+ LocalTensor<uint8_t> &sharedTmpBuffer, uint32_t calCount) {
135+ ReduceExtendInternal::ReduceXorSumCompute<T, isReuseSource>(dst, src0, src1, sharedTmpBuffer, calCount);
136+}
137+ 
138+template <typename T, bool isReuseSource = false>
139+__aicore__ inline void ReduceXorSumExtend(LocalTensor<T> &dst, const LocalTensor<T> &src0, const LocalTensor<T> &src1,
140+ uint32_t calCount) {
141+ LocalTensor<uint8_t> sharedTmpBuffer;
142+ bool ans = PopStackBuffer<uint8_t, TPosition::LCM>(sharedTmpBuffer);
143+ ASCENDC_ASSERT((ans), { KERNEL_LOG(KERNEL_ERROR, "PopStackBuffer Error!"); });
144+ ReduceXorSumExtend<T, isReuseSource>(dst, src0, src1, sharedTmpBuffer, calCount);
145+}
146+} // namespace AscendC
147+ 
148+#endif // AUTOFUSE_V35_ASCENDC_API_REGBASE_REDUCE_EXTEND_H
@@ -2527,7 +2527,7 @@ class MaxAscIrCodegenImplV2 : public AscIrCodegenV2 {
2527 return "ReduceMax";2527 return "ReduceMax";
2528 }2528 }
2529 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2529 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2530- return {"reduce_init_reg_base.h"};2530+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2531 }2531 }
2532 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(2532 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(
2533 const AscNode &node) {2533 const AscNode &node) {
@@ -2561,7 +2561,7 @@ class SumAscIrCodegenImplV2 : public AscIrCodegenV2 {
2561 return "ReduceSum";2561 return "ReduceSum";
2562 }2562 }
2563 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2563 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2564- return {"reduce_init_reg_base.h"};2564+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2565 }2565 }
2566 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(2566 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(
2567 const AscNode &node) {2567 const AscNode &node) {
@@ -2598,7 +2598,7 @@ class MinAscIrCodegenImplV2 : public AscIrCodegenV2 {
2598 return "ReduceMin";2598 return "ReduceMin";
2599 }2599 }
2600 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2600 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2601- return {"reduce_init_reg_base.h"};2601+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2602 }2602 }
2603 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(2603 [[nodiscard]] std::pair<std::vector<ge::DataType>, std::vector<ge::DataType>> GetConversionDtype(
2604 const AscNode &node) {2604 const AscNode &node) {
@@ -2632,7 +2632,7 @@ class MeanAscIrCodegenImplV2 : public AscIrCodegenV2 {
2632 return "ReduceMean";2632 return "ReduceMean";
2633 }2633 }
2634 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2634 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2635- return {"reduce_init_reg_base.h"};2635+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2636 }2636 }
2637 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {2637 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {
2638 return {2638 return {
@@ -2661,7 +2661,7 @@ class ProdAscIrCodegenImplV2 : public AscIrCodegenV2 {
2661 return "ReduceProd";2661 return "ReduceProd";
2662 }2662 }
2663 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2663 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2664- return {"reduce_init_reg_base.h"};2664+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2665 }2665 }
2666 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {2666 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {
2667 return {2667 return {
@@ -2690,7 +2690,7 @@ class AnyAscIrCodegenImplV2 : public AscIrCodegenV2 {
2690 return "ReduceAny";2690 return "ReduceAny";
2691 }2691 }
2692 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2692 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2693- return {"reduce_init_reg_base.h"};2693+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2694 }2694 }
2695 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {2695 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {
2696 return {2696 return {
@@ -2719,7 +2719,7 @@ class AllAscIrCodegenImplV2 : public AscIrCodegenV2 {
2719 return "ReduceAll";2719 return "ReduceAll";
2720 }2720 }
2721 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {2721 [[nodiscard]] std::vector<std::string> LoadApiHeaderFiles([[maybe_unused]] bool is_dynamic) const override {
2722- return {"reduce_init_reg_base.h"};2722+ return {"reduce_init_reg_base.h", "reduce_extend_reg_base.h"};
2723 }2723 }
2724 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {2724 [[nodiscard]] std::vector<std::string> IncludeApiHeaderFiles() const override {
2725 return {2725 return {
@@ -32,6 +32,21 @@ static std::string StripBroadcastSelfIncludes(const std::string &src) {
32 return result;32 return result;
33}33}
34 34 
35+static std::string StripReduceSelfIncludes(const std::string &src) {
36+ std::string result;
37+ size_t pos = 0;
38+ while (pos < src.size()) {
39+ size_t end = src.find('\n', pos);
40+ if (end == std::string::npos) end = src.size();
41+ std::string line = src.substr(pos, end - pos);
42+ if (line.find("#include \"reduce/") == std::string::npos) {
43+ result += line + "\n";
44+ }
45+ pos = end + 1;
46+ }
47+ return result;
48+}
49+ 
35Register::Register() {50Register::Register() {
36 const std::string kAscendcCastRegStr = {51 const std::string kAscendcCastRegStr = {
37#include "cast_reg_base.h"52#include "cast_reg_base.h"
@@ -63,6 +78,57 @@ Register::Register() {
63 const std::string kAscendcReduce_initRegBase = {78 const std::string kAscendcReduce_initRegBase = {
64#include "reduce_init_reg_base.h"79#include "reduce_init_reg_base.h"
65 };80 };
81+ const std::string kAscendcReduceExtendRegBase = StripReduceSelfIncludes(std::string{
82+#include "reduce/reduce_common_reg_base.h"
83+ }) +
84+ StripReduceSelfIncludes(std::string{
85+#include "reduce/reduce_common_util_3510_impl_reg_base.h"
86+ }) +
87+ StripReduceSelfIncludes(std::string{
88+#include "reduce/reduce_common_ar_reuse_align_less_than_vl_3510_impl_reg_base.h"
89+ }) +
90+ StripReduceSelfIncludes(std::string{
91+#include "reduce/reduce_common_ar_reuse_align_3510_impl_reg_base.h"
92+ }) +
93+ StripReduceSelfIncludes(std::string{
94+#include "reduce/reduce_common_ra_reuse_align_3510_impl_reg_base.h"
95+ }) +
96+ StripReduceSelfIncludes(std::string{
97+#include "reduce/reduce_common_ar_ra_reuse_unalign_3510_impl_reg_base.h"
98+ }) +
99+ StripReduceSelfIncludes(std::string{
100+#include "reduce/reduce_sum_3510_impl_reg_base.h"
101+ }) +
102+ StripReduceSelfIncludes(std::string{
103+#include "reduce/reduce_mean_3510_impl_reg_base.h"
104+ }) +
105+ StripReduceSelfIncludes(std::string{
106+#include "reduce/reduce_max_3510_impl_reg_base.h"
107+ }) +
108+ StripReduceSelfIncludes(std::string{
109+#include "reduce/reduce_min_3510_impl_reg_base.h"
110+ }) +
111+ StripReduceSelfIncludes(std::string{
112+#include "reduce/reduce_prod_3510_impl_reg_base.h"
113+ }) +
114+ StripReduceSelfIncludes(std::string{
115+#include "reduce/reduce_any_3510_impl_reg_base.h"
116+ }) +
117+ StripReduceSelfIncludes(std::string{
118+#include "reduce/reduce_all_3510_impl_reg_base.h"
119+ }) +
120+ StripReduceSelfIncludes(std::string{
121+#include "reduce/mean_3510_impl_reg_base.h"
122+ }) +
123+ StripReduceSelfIncludes(std::string{
124+#include "reduce/sum_3510_impl_reg_base.h"
125+ }) +
126+ StripReduceSelfIncludes(std::string{
127+#include "reduce/reduce_xor_sum_3510_impl_reg_base.h"
128+ }) +
129+ StripReduceSelfIncludes(std::string{
130+#include "reduce_extend_reg_base.h"
131+ });
66 const std::string kAscendcFloorDivRegBaseStr = {132 const std::string kAscendcFloorDivRegBaseStr = {
67#include "floor_div_reg_base.h"133#include "floor_div_reg_base.h"
68 };134 };
@@ -352,6 +418,7 @@ Register::Register() {
352 {"erf_reg_base.h", kAscendcErfRegBaseStr},418 {"erf_reg_base.h", kAscendcErfRegBaseStr},
353 {"tanh_reg_base.h", kAscendcTanhRegBaseStr},419 {"tanh_reg_base.h", kAscendcTanhRegBaseStr},
354 {"reduce_init_reg_base.h", kAscendcReduce_initRegBase},420 {"reduce_init_reg_base.h", kAscendcReduce_initRegBase},
421+ {"reduce_extend_reg_base.h", kAscendcReduceExtendRegBase},
355 {"floor_div_reg_base.h", kAscendcFloorDivRegBaseStr},422 {"floor_div_reg_base.h", kAscendcFloorDivRegBaseStr},
356 {"sign_reg_base.h", kAscendcSignRegBaseStr},423 {"sign_reg_base.h", kAscendcSignRegBaseStr},
357 {"where_reg_base.h", kAscendcWhereRegBaseStr},424 {"where_reg_base.h", kAscendcWhereRegBaseStr},
@@ -78,7 +78,7 @@ Status RegReduceApiCall::BuildApiParam(const TPipe &tpipe, const std::vector<asc
78 78 
79 ReduceInitCodeGen(x, y, type_value, api_param->api_pre_process, tpipe, dtype_name);79 ReduceInitCodeGen(x, y, type_value, api_param->api_pre_process, tpipe, dtype_name);
80 api_param->api_pre_process.emplace_back("uint32_t tmp_reduce_shape[] = {first_actual, last};\n");80 api_param->api_pre_process.emplace_back("uint32_t tmp_reduce_shape[] = {first_actual, last};\n");
81- std::string new_api_name = this->api_name_ == "ReduceMean" ? "ReduceSum" : this->api_name_;81+ std::string new_api_name = this->api_name_ == "ReduceMean" ? "ReduceSumExtend" : this->api_name_ + "Extend";
82 api_param->api_name = new_api_name;82 api_param->api_name = new_api_name;
83 api_param->template_params.emplace_back(dtype_name);83 api_param->template_params.emplace_back(dtype_name);
84 api_param->template_params.emplace_back(reduce_pattern);84 api_param->template_params.emplace_back(reduce_pattern);