blob: ee8f6f28f0b49bf29550e072bfe09eea5e87e8b0 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
Francis Murtagh0d7963c2024-01-17 09:39:30 +00002// Copyright © 2017-2024 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
6#include "NeonLayerSupport.hpp"
Sadik Armagan045f6be2020-09-10 13:37:32 +01007#include "NeonBackendModelContext.hpp"
telsoa014fcda012018-03-09 14:13:49 +00008
Derek Lambertic77874a2020-04-28 13:34:56 +01009#include <armnn/Exceptions.hpp>
telsoa014fcda012018-03-09 14:13:49 +000010#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010011#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000012#include <armnn/BackendRegistry.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
Matteo Martincighc601aa62019-10-29 15:03:22 +000014#include <LayerSupportCommon.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000015#include <armnn/utility/IgnoreUnused.hpp>
Francis Murtagh0d7963c2024-01-17 09:39:30 +000016#include <armnn/utility/NumericCast.hpp>
Sadik Armagan045f6be2020-09-10 13:37:32 +010017#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000018
Matteo Martincighd95e9062019-01-31 15:35:59 +000019#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010020#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar710f6642019-11-27 14:48:32 +000021#include <aclCommon/ArmComputeTensorUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010022#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000023#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010024#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010025#include "workloads/NeonArgMinMaxWorkload.hpp"
Teresa Charlin0f86ecf2022-10-13 15:47:08 +010026#include "workloads/NeonBatchMatMulWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000027#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000028#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010029#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010030#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010031#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010032#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010033#include "workloads/NeonConstantWorkload.hpp"
Matthew Bentham34336f92023-04-27 12:13:50 +000034#include "workloads/NeonConvertFp16ToFp32Workload.hpp"
35#include "workloads/NeonConvertFp32ToFp16Workload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010036#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010037#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010038#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010039#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010040#include "workloads/NeonDequantizeWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010041#include "workloads/NeonDivisionWorkload.hpp"
John Mcloughlin34c1c382023-05-17 15:08:36 +010042#include "workloads/NeonElementwiseBinaryWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010043#include "workloads/NeonExpWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010044#include "workloads/NeonFullyConnectedWorkload.hpp"
45#include "workloads/NeonFusedWorkload.hpp"
46#include "workloads/NeonGatherWorkload.hpp"
47#include "workloads/NeonGatherNdWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010048#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010049#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010050#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010051#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000052#include "workloads/NeonLogicalAndWorkload.hpp"
53#include "workloads/NeonLogicalNotWorkload.hpp"
54#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010055#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000056#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000057#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000058#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000059#include "workloads/NeonMultiplicationWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000060#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010061#include "workloads/NeonNormalizationFloatWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000062#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010063#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010064#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010065#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010066#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010067#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010068#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010069#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000070#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000071#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010072#include "workloads/NeonResizeWorkload.hpp"
Tianle Cheng21a9f332023-11-09 13:56:53 +000073#include "workloads/NeonReverseV2Workload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010074#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010075#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060076#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010077#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000078#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010079#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010080#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010081#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010082#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010083#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000084#include "workloads/NeonSubtractionWorkload.hpp"
David Monahan36e6eae2023-07-26 18:37:45 +010085#include "workloads/NeonTileWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010086#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000087#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000088#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010089#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000090#endif
91
telsoa014fcda012018-03-09 14:13:49 +000092namespace armnn
93{
telsoa014fcda012018-03-09 14:13:49 +000094
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010095namespace
arovir017ff76c52018-10-09 09:40:58 +010096{
telsoa014fcda012018-03-09 14:13:49 +000097
Cathal Corbett80f71a82022-12-20 18:25:40 +000098const TensorInfo OverrideDataType(const TensorInfo& info, Optional<DataType> type)
99{
100 if (!type)
101 {
102 return info;
103 }
104 return TensorInfo(info.GetShape(),
105 type.value(),
106 info.GetQuantizationScale(),
107 info.GetQuantizationOffset(),
108 info.IsConstant());
109}
110
Derek Lamberti901ea112019-12-10 22:07:09 +0000111template< typename ... Args>
112bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +0000113{
Jan Eilers8eb25602020-03-09 12:13:48 +0000114 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +0000115#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000116 return true;
117#else
Derek Lamberti0790dce2019-04-15 18:37:35 +0100118 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +0000119 return false;
120#endif
121}
122
telsoa01c577f2c2018-08-31 09:22:23 +0100123template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100124bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000125 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100126 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000127 Uint8Func uint8FuncPtr,
128 Params&&... params)
129{
130 return IsNeonBackendSupported(reasonIfUnsupported) &&
131 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
Teresa Charlin9145e382023-08-17 18:44:58 +0100132 dataType,
133 floatFuncPtr,
134 floatFuncPtr,
135 uint8FuncPtr,
136 &FalseFunc<>,
137 &FalseFunc<>,
138 std::forward<Params>(params)...);
telsoa014fcda012018-03-09 14:13:49 +0000139}
140
Matteo Martincighd95e9062019-01-31 15:35:59 +0000141#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000142template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100143inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000144{
145 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
146 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
147 if (!supported && reasonIfUnsupported)
148 {
arovir01085f0a42018-10-08 14:48:19 +0100149 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000150 }
151 return supported;
152}
153
154#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
155 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
156#else
157#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000158 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000159#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100160} // anonymous namespace
161
Sadik Armagan045f6be2020-09-10 13:37:32 +0100162NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
163 : m_ModelContextPtr(modelContextPtr)
164{
165}
166
167NeonLayerSupport::NeonLayerSupport()
168 : m_ModelContextPtr(nullptr)
169{
170}
171
Cathal Corbett80f71a82022-12-20 18:25:40 +0000172bool IsLayerTypeSupported(const LayerType& type,
173 const std::vector<TensorInfo>& infos,
174 const BaseDescriptor& descriptor,
175 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
176 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
177 Optional<std::string&> reasonIfUnsupported,
178 const NeonLayerSupport& support)
Cathal Corbett34b429c2021-12-24 12:24:40 +0000179{
180 switch (type)
181 {
182 case LayerType::Activation:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000183 return support.IsActivationSupported(infos[0],
184 infos[1],
185 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
186 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000187 case LayerType::Addition:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000188 return support.IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000189 case LayerType::ArgMinMax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000190 return support.IsArgMinMaxSupported(infos[0],
191 infos[1],
192 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
193 reasonIfUnsupported);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100194 case LayerType::BatchMatMul:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000195 return support.IsBatchMatMulSupported(infos[0],
196 infos[1],
197 infos[2],
198 *(PolymorphicDowncast<const BatchMatMulDescriptor*>(&descriptor)),
199 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000200 case LayerType::BatchNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000201 return support.IsBatchNormalizationSupported(infos[0],
202 infos[1],
203 infos[2],
204 infos[3],
205 infos[4],
206 infos[5],
207 *(PolymorphicDowncast<const
208 BatchNormalizationDescriptor*>(&descriptor)),
209 reasonIfUnsupported);
210 case LayerType::BatchToSpaceNd:
211 return support.IsBatchToSpaceNdSupported(infos[0],
212 infos[1],
213 *(PolymorphicDowncast<const
214 BatchToSpaceNdDescriptor*>(&descriptor)),
215 reasonIfUnsupported);
216 case LayerType::Cast:
217 return support.IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
218 case LayerType::ChannelShuffle:
219 return support.IsChannelShuffleSupported(infos[0],
220 infos[1],
221 *(PolymorphicDowncast<const
222 ChannelShuffleDescriptor*>(&descriptor)),
223 reasonIfUnsupported);
224 case LayerType::Comparison:
225 return support.IsComparisonSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000226 infos[1],
227 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000228 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000229 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000230 case LayerType::Concat:
231 {
232 std::vector<const TensorInfo*> inputInfos;
233 for (uint32_t i = 0; i < (infos.size() - 1); i++)
234 {
235 inputInfos.push_back(&infos[i]);
236 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000237 return support.IsConcatSupported(inputInfos,
238 infos[infos.size() - 1],
239 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
240 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000241 }
242 case LayerType::Constant:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000243 return support.IsConstantSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000244 case LayerType::ConvertFp16ToFp32:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000245 return support.IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000246 case LayerType::ConvertFp32ToFp16:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000247 return support.IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000248 case LayerType::Convolution2d:
249 {
250 if (infos.size() != 4)
251 {
252 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
253 "TensorInfos should be of format: {input, output, weights, biases}.");
254 }
255
256 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
257 if (infos[3] == TensorInfo())
258 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000259 return support.IsConvolution2dSupported(infos[0],
260 infos[1],
261 desc,
262 infos[2],
263 EmptyOptional(),
264 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000265 }
266 else
267 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000268 return support.IsConvolution2dSupported(infos[0],
269 infos[1],
270 desc,
271 infos[2],
272 infos[3],
273 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000274 }
275 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000276 case LayerType::Convolution3d:
277 {
278 if (infos.size() != 4)
279 {
280 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
281 "TensorInfos should be of format: {input, output, weights, biases}.");
282 }
283
284 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
285 if (infos[3] == TensorInfo())
286 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000287 return support.IsConvolution3dSupported(infos[0],
288 infos[1],
289 desc,
290 infos[2],
291 EmptyOptional(),
292 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000293 }
294 else
295 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000296 return support.IsConvolution3dSupported(infos[0],
297 infos[1],
298 desc,
299 infos[2],
300 infos[3],
301 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000302 }
303 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000304 case LayerType::DepthToSpace:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000305 return support.IsDepthToSpaceSupported(infos[0],
306 infos[1],
307 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
308 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000309 case LayerType::DepthwiseConvolution2d:
310 {
311 if (infos.size() != 4)
312 {
313 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
314 "TensorInfos should be of format: {input, output, weights, biases}.");
315 }
316
317 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
318 if (infos[3] == TensorInfo())
319 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000320 return support.IsDepthwiseConvolutionSupported(infos[0],
321 infos[1],
322 desc,
323 infos[2],
324 EmptyOptional(),
325 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000326 }
327 else
328 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000329 return support.IsDepthwiseConvolutionSupported(infos[0],
330 infos[1],
331 desc,
332 infos[2],
333 infos[3],
334 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000335 }
336 }
337 case LayerType::Dequantize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000338 return support.IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000339 case LayerType::DetectionPostProcess:
340 {
341 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
Cathal Corbett80f71a82022-12-20 18:25:40 +0000342 return support.IsDetectionPostProcessSupported(infos[0],
343 infos[1],
344 infos[2],
345 infos[3],
346 infos[4],
347 infos[5],
348 infos[6],
349 desc,
350 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000351 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000352 case LayerType::Division:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000353 return support.IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Mike Kelly3ec30772023-03-08 13:47:17 +0000354 case LayerType::ElementwiseBinary:
355 {
356 auto desc = *(PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor));
357
358 switch (desc.m_Operation)
359 {
360 case BinaryOperation::Add:
361 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
362 reasonIfUnsupported,
363 infos[0],
364 infos[1],
365 infos[2],
366 nullptr);
367 case BinaryOperation::Div:
368 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
369 reasonIfUnsupported,
370 infos[0],
371 infos[1],
372 infos[2],
373 nullptr);
374 case BinaryOperation::Maximum:
375 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
376 reasonIfUnsupported,
377 infos[0],
378 infos[1],
379 infos[2]);
380 case BinaryOperation::Minimum:
381 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
382 reasonIfUnsupported,
383 infos[0],
384 infos[1],
385 infos[2]);
386 case BinaryOperation::Mul:
387 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
388 reasonIfUnsupported,
389 infos[0],
390 infos[1],
391 infos[2],
392 nullptr);
John Mcloughlin34c1c382023-05-17 15:08:36 +0100393 case BinaryOperation::Power:
394 case BinaryOperation::SqDiff:
395 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonElementwiseBinaryWorkloadValidate,
396 reasonIfUnsupported,
397 infos[0],
398 infos[1],
399 infos[2],
400 desc,
401 nullptr);
Mike Kelly3ec30772023-03-08 13:47:17 +0000402 case BinaryOperation::Sub:
403 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
404 reasonIfUnsupported,
405 infos[0],
406 infos[1],
407 infos[2],
408 nullptr);
409 default:
410 return false;
411 }
412 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000413 case LayerType::ElementwiseUnary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000414 return support.IsElementwiseUnarySupported(infos[0],
415 infos[1],
416 *(PolymorphicDowncast<const
417 ElementwiseUnaryDescriptor*>(&descriptor)),
418 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000419 case LayerType::Fill:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000420 return support.IsFillSupported(infos[0],
421 infos[1],
422 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
423 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000424 case LayerType::Floor:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000425 return support.IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000426 case LayerType::FullyConnected:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000427 return support.IsFullyConnectedSupported(infos[0],
428 infos[1],
429 infos[2],
430 infos[3],
431 *(PolymorphicDowncast<const
432 FullyConnectedDescriptor*>(&descriptor)),
433 reasonIfUnsupported);
Teresa Charlin9145e382023-08-17 18:44:58 +0100434 case LayerType::Fused:
435 {
436 auto fusedDescriptor = *(PolymorphicDowncast<const FusedDescriptor*>(&descriptor));
437 if (fusedDescriptor.m_NumInputSlots + fusedDescriptor.m_NumOutputSlots != infos.size())
438 {
439 throw InvalidArgumentException("Invalid number of FusedLayer TensorInfos.");
440 }
441
Francis Murtagh0d7963c2024-01-17 09:39:30 +0000442 auto it = infos.begin() + numeric_cast<TensorInfo::DifferenceType>(fusedDescriptor.m_NumInputSlots);
443 std::vector<TensorInfo> inputInfos(infos.begin(), it);
444 std::vector<TensorInfo> outputInfos(it, infos.end());
Teresa Charlin9145e382023-08-17 18:44:58 +0100445
446 return support.IsFusedSupported({inputInfos.begin(), inputInfos.end()},
447 {outputInfos.begin(), outputInfos.end()},
448 fusedDescriptor,
449 reasonIfUnsupported);
450 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000451 case LayerType::Gather:
452 return support.IsGatherSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000453 infos[1],
454 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000455 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000456 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100457 case LayerType::GatherNd:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000458 return support.IsGatherNdSupported(infos[0],
459 infos[1],
460 infos[2],
461 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000462 case LayerType::Input:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000463 return support.IsInputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000464 case LayerType::InstanceNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000465 return support.IsInstanceNormalizationSupported(infos[0],
466 infos[1],
467 *(PolymorphicDowncast<const
468 InstanceNormalizationDescriptor*>(&descriptor)),
469 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000470 case LayerType::L2Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000471 return support.IsL2NormalizationSupported(infos[0],
472 infos[1],
473 *(PolymorphicDowncast<const
474 L2NormalizationDescriptor*>(&descriptor)),
475 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000476 case LayerType::LogicalBinary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000477 return support.IsLogicalBinarySupported(infos[0],
478 infos[1],
479 infos[2],
480 *(PolymorphicDowncast<const
481 LogicalBinaryDescriptor*>(&descriptor)),
482 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000483 case LayerType::LogSoftmax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000484 return support.IsLogSoftmaxSupported(infos[0],
485 infos[1],
486 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
487 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000488 case LayerType::Lstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000489 return support.IsLstmSupported(infos[0],
490 infos[1],
491 infos[2],
492 infos[3],
493 infos[4],
494 infos[5],
495 infos[6],
496 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
497 lstmParamsInfo.value(),
498 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000499 case LayerType::Map:
500 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000501 case LayerType::Maximum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000502 return support.IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000503 case LayerType::Mean:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000504 return support.IsMeanSupported(infos[0],
505 infos[1],
506 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
507 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000508 case LayerType::MemCopy:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000509 return support.IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000510 case LayerType::MemImport:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000511 return support.IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000512 case LayerType::Merge:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000513 return support.IsMergeSupported(infos[0],
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000514 infos[1],
515 infos[2],
516 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000517 case LayerType::Minimum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000518 return support.IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000519 case LayerType::Multiplication:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000520 return support.IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000521 case LayerType::Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000522 return support.IsNormalizationSupported(infos[0],
523 infos[1],
524 *(PolymorphicDowncast<const
525 NormalizationDescriptor*>(&descriptor)),
526 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000527 case LayerType::Output:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000528 return support.IsOutputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000529 case LayerType::Pad:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000530 return support.IsPadSupported(infos[0],
531 infos[1],
532 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
533 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000534 case LayerType::Permute:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000535 return support.IsPermuteSupported(infos[0],
536 infos[1],
537 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
538 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000539 case LayerType::Pooling2d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000540 return support.IsPooling2dSupported(infos[0],
541 infos[1],
542 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
543 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100544 case LayerType::Pooling3d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000545 return support.IsPooling3dSupported(infos[0],
546 infos[1],
547 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
548 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000549 case LayerType::Prelu:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000550 return support.IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000551 case LayerType::QLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000552 return support.IsQLstmSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000553 infos[1],
554 infos[2],
555 infos[3],
556 infos[4],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000557 infos[5],
558 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
559 lstmParamsInfo.value(),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000560 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000561 case LayerType::Quantize:
562 return support.IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
563 case LayerType::QuantizedLstm:
564 return support.IsQuantizedLstmSupported(infos[0],
565 infos[1],
566 infos[2],
567 infos[3],
568 infos[4],
569 quantizedLstmParamsInfo.value(),
570 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000571 case LayerType::Rank:
572 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000573 case LayerType::Reshape:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000574 return support.IsReshapeSupported(infos[0],
575 infos[1],
576 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
577 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000578 case LayerType::Resize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000579 return support.IsResizeSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000580 infos[1],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000581 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000582 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000583 case LayerType::Reduce:
584 return support.IsReduceSupported(infos[0],
585 infos[1],
586 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
587 reasonIfUnsupported);
Tianle Cheng21a9f332023-11-09 13:56:53 +0000588 case LayerType::ReverseV2:
589 return support.IsReverseV2Supported(infos[0],
590 infos[1],
591 infos[2],
592 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000593 case LayerType::Shape:
594 return support.IsShapeSupported(infos[0],
595 infos[1],
596 reasonIfUnsupported);
597 case LayerType::Slice:
598 return support.IsSliceSupported(infos[0],
599 infos[1],
600 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
601 reasonIfUnsupported);
602 case LayerType::Softmax:
603 return support.IsSoftmaxSupported(infos[0],
604 infos[1],
605 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
606 reasonIfUnsupported);
607 case LayerType::SpaceToBatchNd:
608 return support.IsSpaceToBatchNdSupported(infos[0],
609 infos[1],
610 *(PolymorphicDowncast<const
611 SpaceToBatchNdDescriptor*>(&descriptor)),
612 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000613 case LayerType::SpaceToDepth:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000614 return support.IsSpaceToDepthSupported(infos[0],
615 infos[1],
616 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
617 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000618 case LayerType::Splitter:
619 {
620 std::vector<TensorInfo> outputInfos;
621 for (uint32_t i = 1; i < infos.size(); i++)
622 {
623 outputInfos.push_back(infos[i]);
624 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000625 return support.IsSplitterSupported(infos[0],
626 {outputInfos.begin(), outputInfos.end()},
627 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
628 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000629 }
630 case LayerType::Stack:
631 {
632 std::vector<const TensorInfo*> inputInfos;
633 for (uint32_t i = 0; i < infos.size() - 1; i++)
634 {
635 inputInfos.push_back(&infos[i]);
636 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000637 return support.IsStackSupported(inputInfos,
638 infos[infos.size() - 1],
639 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
640 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000641 }
642 case LayerType::StridedSlice:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000643 return support.IsStridedSliceSupported(infos[0],
644 infos[1],
645 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
646 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000647 case LayerType::Subtraction:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000648 return support.IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
David Monahan36e6eae2023-07-26 18:37:45 +0100649 case LayerType::Tile:
650 return support.IsTileSupported(infos[0],
651 infos[1],
652 *(PolymorphicDowncast<const TileDescriptor*>(&descriptor)),
653 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000654 case LayerType::Transpose:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000655 return support.IsTransposeSupported(infos[0],
656 infos[1],
657 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
658 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000659 case LayerType::TransposeConvolution2d:
660 {
661 if (infos.size() != 4)
662 {
663 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
664 "TensorInfos should be of format: {input, output, weights, biases}.");
665 }
666
667 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
668 if (infos[3] == TensorInfo())
669 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000670 return support.IsTransposeConvolution2dSupported(infos[0],
671 infos[1],
672 desc,
673 infos[2],
674 EmptyOptional(),
675 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000676 }
677 else
678 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000679 return support.IsTransposeConvolution2dSupported(infos[0],
680 infos[1],
681 desc,
682 infos[2],
683 infos[3],
684 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000685 }
686 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000687 case LayerType::UnidirectionalSequenceLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000688 {
689 auto desc = *(PolymorphicDowncast<const UnidirectionalSequenceLstmDescriptor*>(&descriptor));
690 return support.IsUnidirectionalSequenceLstmSupported(infos[0],
691 infos[1],
692 infos[2],
693 infos[3],
694 infos[4],
695 infos[5],
696 desc,
697 lstmParamsInfo.value(),
698 reasonIfUnsupported);
699 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000700 case LayerType::Unmap:
701 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000702 default:
703 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000704 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100705 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000706 return false;
707 }
708}
709
Cathal Corbett80f71a82022-12-20 18:25:40 +0000710bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
711 const std::vector<TensorInfo>& infos,
712 const BaseDescriptor& descriptor,
713 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
714 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
715 Optional<std::string&> reasonIfUnsupported) const
716{
717 bool isSupported = IsLayerTypeSupported(type,
718 infos,
719 descriptor,
720 lstmParamsInfo,
721 quantizedLstmParamsInfo,
722 reasonIfUnsupported,
723 *this);
724
725 // For android-nn-driver and support library, to run FP16 operations on CpuAcc we need at least v8.2
726 // architecture. If the available architecture is older than v8.2, we can check if the operator is
727 // supported by changing operator inputs & outputs to be FP32.
728 // This does not change the operator datatype in the above parsers to be FP32. We are simply reporting
729 // to the parsers if the operator can supported in ArmNN. We will then re-enter ArmNN (Network.cpp)
730 // where we will recheck IsLayerSupported() on the FP16 datatype, update the operator to be FP32,
731 // and, insert convert layers around the FP32 operator.
732 if (reasonIfUnsupported.has_value())
733 {
734 std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
735 if (!isSupported
736 && reasonIfUnsupported.value().find(checkStr) != std::string::npos)
737 {
738 std::vector<TensorInfo> newInfos;
739 for (auto info: infos)
740 {
741 newInfos.emplace_back(OverrideDataType(info, DataType::Float32));
742 }
743
744 std::string tmpString;
745 return IsLayerTypeSupported(type,
746 newInfos,
747 descriptor,
748 lstmParamsInfo,
749 quantizedLstmParamsInfo,
750 tmpString,
751 *this);
752 }
753 }
754
755 return isSupported;
756}
757
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100758bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
759 const TensorInfo& output,
760 const ActivationDescriptor& descriptor,
761 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000762{
Jan Eilers8eb25602020-03-09 12:13:48 +0000763 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100764 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
765 reasonIfUnsupported,
766 input,
767 output,
768 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000769}
770
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100771bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
772 const TensorInfo& input1,
773 const TensorInfo& output,
774 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000775{
telsoa01c577f2c2018-08-31 09:22:23 +0100776 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
777 reasonIfUnsupported,
778 input0,
779 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000780 output,
781 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000782}
783
James Conroyd47a0642019-09-17 14:22:06 +0100784bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
785 const TensorInfo& output,
786 const ArgMinMaxDescriptor& descriptor,
787 Optional<std::string&> reasonIfUnsupported) const
788{
789 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
790 reasonIfUnsupported,
791 input,
792 output,
793 descriptor);
794}
795
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100796bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
797 const TensorInfo& inputY,
798 const TensorInfo& output,
799 const BatchMatMulDescriptor& descriptor,
800 Optional<std::string&> reasonIfUnsupported) const
801{
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000802 bool isFastMathEnabled = false;
803#if defined(ARMCOMPUTENEON_ENABLED)
804 if (m_ModelContextPtr)
805 {
806 if (m_ModelContextPtr.get() != nullptr)
807 {
808 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
809 if (modelOptions)
810 {
811 isFastMathEnabled = modelOptions->IsFastMathEnabled();
812 }
813 }
814 }
815#endif
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100816 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
817 reasonIfUnsupported,
818 inputX,
819 inputY,
820 output,
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000821 descriptor,
822 isFastMathEnabled,
823 nullptr);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100824}
825
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100826bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
827 const TensorInfo& output,
828 const TensorInfo& mean,
829 const TensorInfo& var,
830 const TensorInfo& beta,
831 const TensorInfo& gamma,
832 const BatchNormalizationDescriptor& descriptor,
833 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000834{
telsoa01c577f2c2018-08-31 09:22:23 +0100835 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
836 reasonIfUnsupported,
837 input,
838 output,
839 mean,
840 var,
841 beta,
842 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000843 descriptor,
844 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000845}
846
Mike Kelly56858022020-01-27 12:14:47 +0000847bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
848 const TensorInfo& output,
849 const BatchToSpaceNdDescriptor& descriptor,
850 Optional<std::string&> reasonIfUnsupported) const
851{
852 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
853 reasonIfUnsupported,
854 input,
855 output,
856 descriptor);
857}
858
Sadik Armagan48f011e2021-04-21 10:50:34 +0100859bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
860 const TensorInfo& output,
861 Optional<std::string&> reasonIfUnsupported) const
862{
863 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
864 reasonIfUnsupported,
865 input,
866 output);
867}
868
Teresa Charline89dd692021-09-01 16:30:34 +0100869bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
870 const TensorInfo& output,
871 const ChannelShuffleDescriptor& descriptor,
872 Optional<std::string&> reasonIfUnsupported) const
873{
874 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
875 reasonIfUnsupported,
876 input,
877 output,
878 descriptor);
879}
880
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100881bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
882 const TensorInfo& input1,
883 const TensorInfo& output,
884 const ComparisonDescriptor& descriptor,
885 Optional<std::string&> reasonIfUnsupported) const
886{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100887
Teresa Charlincedd34f2020-03-30 11:17:30 +0100888 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
889 reasonIfUnsupported,
890 input0,
891 input1,
892 output,
893 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100894}
895
Jim Flynn906f9462019-05-10 13:55:21 +0100896bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
897 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000898 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100899 Optional<std::string&> reasonIfUnsupported) const
900{
Jim Flynne242f2d2019-05-22 14:24:13 +0100901 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
902 {
903 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
904 return false;
905 }
906
907 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
908 if(concatInnerAxis < 3) // Width, height, or channels
909 {
910 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
911 reasonIfUnsupported,
912 inputs,
913 output,
914 descriptor);
915 }
916 else if (concatInnerAxis == 3)
917 {
918 for (auto& input : inputs)
919 {
920 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
921 {
922 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
923 return false;
924 }
925 }
926 return true; // Sub-tensors support concat along batch
927 }
928 else // > 4 dimensions not supported.
929 {
930 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
931 return false;
932 }
Jim Flynn906f9462019-05-10 13:55:21 +0100933}
934
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100935bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
936 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000937{
Mike Kelly0886ac42020-04-27 09:55:40 +0100938 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
939 reasonIfUnsupported,
940 output);
telsoa014fcda012018-03-09 14:13:49 +0000941}
942
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100943bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
944 const TensorInfo& output,
945 Optional<std::string&> reasonIfUnsupported) const
946{
Matthew Bentham34336f92023-04-27 12:13:50 +0000947 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp16ToFp32WorkloadValidate,
948 reasonIfUnsupported,
949 input,
950 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100951}
952
953bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
954 const TensorInfo& output,
955 Optional<std::string&> reasonIfUnsupported) const
956{
Matthew Bentham34336f92023-04-27 12:13:50 +0000957 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp32ToFp16WorkloadValidate,
958 reasonIfUnsupported,
959 input,
960 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100961}
962
963bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
964 const TensorInfo& output,
965 const Convolution2dDescriptor& descriptor,
966 const TensorInfo& weights,
967 const Optional<TensorInfo>& biases,
968 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000969{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100970 bool isFastMathEnabled = false;
971#if defined(ARMCOMPUTENEON_ENABLED)
972 if (m_ModelContextPtr)
973 {
974 if (m_ModelContextPtr.get() != nullptr)
975 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100976 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100977 if (modelOptions)
978 {
979 isFastMathEnabled = modelOptions->IsFastMathEnabled();
980 }
981 }
982 }
983#endif
984
surmeh013537c2c2018-05-18 16:31:43 +0100985 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
986 reasonIfUnsupported,
987 input,
988 output,
989 descriptor,
990 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100991 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000992 isFastMathEnabled,
993 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000994}
995
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100996bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
997 const TensorInfo& output,
998 const Convolution3dDescriptor& descriptor,
999 const TensorInfo& weights,
1000 const Optional<TensorInfo>& biases,
1001 Optional<std::string&> reasonIfUnsupported) const
1002{
1003 bool isFastMathEnabled = false;
1004#if defined(ARMCOMPUTENEON_ENABLED)
1005 if (m_ModelContextPtr)
1006 {
1007 if (m_ModelContextPtr.get() != nullptr)
1008 {
1009 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
1010 if (modelOptions)
1011 {
1012 isFastMathEnabled = modelOptions->IsFastMathEnabled();
1013 }
1014 }
1015 }
1016#endif
1017
1018 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
1019 reasonIfUnsupported,
1020 input,
1021 output,
1022 descriptor,
1023 weights,
1024 biases,
1025 isFastMathEnabled,
1026 nullptr);
1027}
1028
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +01001029bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
1030 const TensorInfo& output,
1031 const DepthToSpaceDescriptor& descriptor,
1032 Optional<std::string&> reasonIfUnsupported) const
1033{
1034 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
1035 reasonIfUnsupported,
1036 input,
1037 output,
1038 descriptor);
1039}
1040
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001041bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
1042 const TensorInfo& output,
1043 const DepthwiseConvolution2dDescriptor& descriptor,
1044 const TensorInfo& weights,
1045 const Optional<TensorInfo>& biases,
1046 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001047{
telsoa01c577f2c2018-08-31 09:22:23 +01001048 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1049 reasonIfUnsupported,
1050 input,
1051 output,
1052 descriptor,
1053 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001054 biases,
1055 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001056}
1057
Narumol Prangnawarat01961a72019-05-30 16:47:12 +01001058bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
1059 const TensorInfo& output,
1060 Optional<std::string&> reasonIfUnsupported) const
1061{
1062 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
1063 reasonIfUnsupported,
1064 input,
1065 output);
1066}
1067
Pablo Tellof0bd6832019-04-26 17:58:13 +01001068bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
1069 const TensorInfo& output,
1070 const DepthwiseConvolution2dDescriptor& descriptor,
1071 const TensorInfo& weights,
1072 const Optional<TensorInfo>& biases,
1073 Optional<std::string&> reasonIfUnsupported) const
1074{
1075 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1076 reasonIfUnsupported,
1077 input,
1078 output,
1079 descriptor,
1080 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001081 biases,
1082 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +01001083}
1084
josh minor4a3c6102020-01-06 16:40:46 -06001085bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
1086 const TensorInfo& output,
1087 const ElementwiseUnaryDescriptor& descriptor,
1088 Optional<std::string&> reasonIfUnsupported) const
1089{
Derek Lambertic77874a2020-04-28 13:34:56 +01001090 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -06001091 {
Derek Lambertic77874a2020-04-28 13:34:56 +01001092 case UnaryOperation::Abs:
1093 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
1094 reasonIfUnsupported,
1095 input,
1096 output);
1097 case UnaryOperation::Exp:
1098 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
1099 reasonIfUnsupported,
1100 input,
1101 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +01001102 case UnaryOperation::LogicalNot:
1103 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
1104 reasonIfUnsupported,
1105 input,
1106 output);
1107 case UnaryOperation::Log:
1108 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
1109 reasonIfUnsupported,
1110 input,
1111 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001112 case UnaryOperation::Neg:
1113 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
1114 reasonIfUnsupported,
1115 input,
1116 output);
1117 case UnaryOperation::Rsqrt:
1118 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
1119 reasonIfUnsupported,
1120 input,
1121 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +00001122 case UnaryOperation::Sin:
1123 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
1124 reasonIfUnsupported,
1125 input,
1126 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +01001127 case UnaryOperation::Sqrt:
1128 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
1129 reasonIfUnsupported,
1130 input,
1131 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001132 default:
1133 return false;
josh minor4a3c6102020-01-06 16:40:46 -06001134 }
josh minor4a3c6102020-01-06 16:40:46 -06001135}
1136
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001137bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
1138 const TensorInfo& output,
1139 const FillDescriptor& descriptor,
1140 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +01001141{
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001142 armnn::IgnoreUnused(input);
1143 armnn::IgnoreUnused(output);
1144 armnn::IgnoreUnused(descriptor);
1145
1146 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +01001147}
1148
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001149bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
1150 const TensorInfo& output,
1151 Optional<std::string&> reasonIfUnsupported) const
1152{
Jan Eilers8eb25602020-03-09 12:13:48 +00001153 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001154 return IsNeonBackendSupported(reasonIfUnsupported) &&
1155 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1156 input.GetDataType(),
1157 &FalseFuncF16<>,
1158 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001159 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001160 &FalseFuncI32<>,
1161 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001162}
1163
1164bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1165 const TensorInfo& output,
1166 const TensorInfo& weights,
1167 const TensorInfo& biases,
1168 const FullyConnectedDescriptor& descriptor,
1169 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001170{
telsoa01c577f2c2018-08-31 09:22:23 +01001171 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1172 reasonIfUnsupported,
1173 input,
1174 output,
1175 weights,
1176 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001177 descriptor,
1178 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001179}
1180
Teresa Charlin9145e382023-08-17 18:44:58 +01001181bool NeonLayerSupport::IsFusedSupported(const std::vector<std::reference_wrapper<TensorInfo>>& inputs,
1182 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1183 const FusedDescriptor& descriptor,
1184 Optional<std::string&> reasonIfUnsupported) const
1185{
1186 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFusedWorkloadValidate,
1187 reasonIfUnsupported,
1188 inputs,
1189 outputs,
1190 descriptor,
1191 nullptr);
1192}
1193
Teresa Charlinf540eb82020-04-10 19:24:55 +01001194bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1195 const TensorInfo& input1,
1196 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001197 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001198 Optional<std::string&> reasonIfUnsupported) const
1199{
1200 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1201 reasonIfUnsupported,
1202 input0,
1203 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001204 output,
1205 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001206}
1207
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001208bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1209 const TensorInfo& input1,
1210 const TensorInfo& output,
1211 Optional<std::string&> reasonIfUnsupported) const
1212{
1213 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1214 reasonIfUnsupported,
1215 input0,
1216 input1,
1217 output);
1218}
1219
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001220bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1221 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001222{
Derek Lamberti901ea112019-12-10 22:07:09 +00001223 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001224}
1225
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001226bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1227 const TensorInfo& output,
1228 const InstanceNormalizationDescriptor& descriptor,
1229 Optional<std::string&> reasonIfUnsupported) const
1230{
1231 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1232 reasonIfUnsupported,
1233 input,
1234 output,
1235 descriptor);
1236}
1237
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001238bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1239 const TensorInfo& output,
1240 const L2NormalizationDescriptor& descriptor,
1241 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001242{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001243 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001244}
1245
James Conroy177df1e2020-11-13 10:18:51 +00001246bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1247 const TensorInfo& input1,
1248 const TensorInfo& output,
1249 const LogicalBinaryDescriptor& descriptor,
1250 Optional<std::string&> reasonIfUnsupported) const
1251{
1252 switch(descriptor.m_Operation)
1253 {
1254 case LogicalBinaryOperation::LogicalAnd:
1255 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1256 reasonIfUnsupported,
1257 input0,
1258 input1,
1259 output);
1260 case LogicalBinaryOperation::LogicalOr:
1261 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1262 reasonIfUnsupported,
1263 input0,
1264 input1,
1265 output);
1266 default:
1267 return false;
1268 }
1269}
1270
Keith Davis69e653f2020-07-02 11:49:26 +01001271bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1272 const TensorInfo& output,
1273 const LogSoftmaxDescriptor& descriptor,
1274 Optional<std::string&> reasonIfUnsupported) const
1275{
1276 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1277}
1278
Jan Eilersad5293a2019-07-08 09:57:55 +01001279bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1280 const TensorInfo& outputStateIn,
1281 const TensorInfo& cellStateIn,
1282 const TensorInfo& scratchBuffer,
1283 const TensorInfo& outputStateOut,
1284 const TensorInfo& cellStateOut,
1285 const TensorInfo& output,
1286 const LstmDescriptor& descriptor,
1287 const LstmInputParamsInfo& paramsInfo,
1288 Optional<std::string&> reasonIfUnsupported) const
1289{
1290 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1291 reasonIfUnsupported,
1292 input,
1293 outputStateIn,
1294 cellStateIn,
1295 scratchBuffer,
1296 outputStateOut,
1297 cellStateOut,
1298 output,
1299 descriptor,
1300 paramsInfo);
1301}
1302
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001303bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1304 const TensorInfo& input1,
1305 const TensorInfo& output,
1306 Optional<std::string&> reasonIfUnsupported) const
1307{
1308 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1309 reasonIfUnsupported,
1310 input0,
1311 input1,
1312 output);
1313}
1314
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001315bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1316 const TensorInfo& output,
1317 const MeanDescriptor& descriptor,
1318 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001319{
Matthew Benthamfd899962018-12-31 15:49:42 +00001320 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1321 reasonIfUnsupported,
1322 input,
1323 output,
1324 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001325}
1326
Conor Kennedy54b21692019-01-09 07:57:38 +00001327bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1328 const TensorInfo& input1,
1329 const TensorInfo& output,
1330 Optional<std::string&> reasonIfUnsupported) const
1331{
1332 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1333 reasonIfUnsupported,
1334 input0,
1335 input1,
1336 output);
1337}
1338
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001339bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1340 const TensorInfo& input1,
1341 const TensorInfo& output,
1342 Optional<std::string&> reasonIfUnsupported) const
1343{
1344 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1345 reasonIfUnsupported,
1346 input0,
1347 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001348 output,
1349 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001350}
1351
Pablo Telloe61f0712020-01-23 10:37:17 +00001352bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1353 const TensorInfo& input1,
1354 const TensorInfo& output,
1355 Optional<std::string&> reasonIfUnsupported) const
1356{
1357 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1358 reasonIfUnsupported,
1359 input0,
1360 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001361 output,
1362 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001363}
1364
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001365bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1366 const TensorInfo& output,
1367 const NormalizationDescriptor& descriptor,
1368 Optional<std::string&> reasonIfUnsupported) const
1369{
1370 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1371 reasonIfUnsupported,
1372 input,
1373 output,
1374 descriptor);
1375}
1376
1377bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1378 Optional<std::string&> reasonIfUnsupported) const
1379{
Derek Lamberti901ea112019-12-10 22:07:09 +00001380 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001381}
1382
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001383bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1384 const TensorInfo& output,
1385 const PadDescriptor& descriptor,
1386 Optional<std::string&> reasonIfUnsupported) const
1387{
1388 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1389 reasonIfUnsupported,
1390 input,
1391 output,
1392 descriptor);
1393}
1394
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001395bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1396 const TensorInfo& output,
1397 const PermuteDescriptor& descriptor,
1398 Optional<std::string&> reasonIfUnsupported) const
1399{
1400 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001401}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001402
1403bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1404 const TensorInfo& output,
1405 const Pooling2dDescriptor& descriptor,
1406 Optional<std::string&> reasonIfUnsupported) const
1407{
1408 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1409}
1410
Ryan OShea19e79422022-05-04 00:38:03 +01001411bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1412 const TensorInfo& output,
1413 const Pooling3dDescriptor& descriptor,
1414 Optional<std::string&> reasonIfUnsupported) const
1415{
1416 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1417}
1418
Nikhil Raj9b461482019-07-03 15:58:31 +01001419bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1420 const armnn::TensorInfo &alpha,
1421 const armnn::TensorInfo &output,
1422 armnn::Optional<std::string &> reasonIfUnsupported) const
1423{
1424 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1425}
1426
James Conroycc340932020-05-12 18:08:52 +01001427bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1428 const TensorInfo& previousOutputIn,
1429 const TensorInfo& previousCellStateIn,
1430 const TensorInfo& outputStateOut,
1431 const TensorInfo& cellStateOut,
1432 const TensorInfo& output,
1433 const QLstmDescriptor& descriptor,
1434 const LstmInputParamsInfo& paramsInfo,
1435 Optional<std::string&> reasonIfUnsupported) const
1436{
1437 // Check required here in order to pass IsLayerSupported for datatypes tests
1438 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1439 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1440 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1441 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1442 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1443 output.GetDataType() == armnn::DataType::QAsymmS8)
1444 {
1445 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1446 reasonIfUnsupported,
1447 input,
1448 previousCellStateIn,
1449 previousOutputIn,
1450 cellStateOut,
1451 outputStateOut,
1452 output,
1453 descriptor,
1454 paramsInfo);
1455 }
1456 else
1457 {
1458 return false;
1459 }
1460}
1461
Sadik Armaganfabc2892019-05-31 09:05:11 +01001462bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1463 const TensorInfo& output,
1464 Optional<std::string&> reasonIfUnsupported) const
1465{
1466 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1467 reasonIfUnsupported,
1468 input,
1469 output);
1470}
1471
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001472bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1473 const TensorInfo& cellStateIn,
1474 const TensorInfo& outputStateIn,
1475 const TensorInfo& cellStateOut,
1476 const TensorInfo& outputStateOut,
1477 const QuantizedLstmInputParamsInfo& paramsInfo,
1478 Optional<std::string&> reasonIfUnsupported) const
1479{
1480 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1481 reasonIfUnsupported,
1482 input,
1483 cellStateIn,
1484 outputStateIn,
1485 cellStateOut,
1486 outputStateOut,
1487 paramsInfo);
1488}
1489
Sadik Armagana2747482021-02-09 10:28:54 +00001490bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1491 const TensorInfo& output,
1492 const ReduceDescriptor& descriptor,
1493 Optional<std::string&> reasonIfUnsupported) const
1494{
1495 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1496 reasonIfUnsupported,
1497 input,
1498 output,
1499 descriptor);
1500}
1501
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001502bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001503 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001504 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001505 Optional<std::string&> reasonIfUnsupported) const
1506{
Jan Eilers8eb25602020-03-09 12:13:48 +00001507 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001508 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1509 reasonIfUnsupported,
1510 input,
1511 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001512}
1513
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001514bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1515 const TensorInfo& output,
1516 const ResizeDescriptor& descriptor,
1517 Optional<std::string&> reasonIfUnsupported) const
1518{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001519 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1520 reasonIfUnsupported,
1521 input,
1522 output,
1523 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001524}
1525
Tianle Cheng21a9f332023-11-09 13:56:53 +00001526bool NeonLayerSupport::IsReverseV2Supported(const armnn::TensorInfo &input,
1527 const armnn::TensorInfo &axis,
1528 const armnn::TensorInfo &output,
1529 Optional<std::string &> reasonIfUnsupported) const
1530{
1531 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReverseV2WorkloadValidate,
1532 reasonIfUnsupported,
1533 input,
1534 axis,
1535 output);
1536}
1537
josh minor036f02d2019-11-15 14:53:22 -06001538bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1539 const TensorInfo& output,
1540 const SliceDescriptor& descriptor,
1541 Optional<std::string&> reasonIfUnsupported) const
1542{
1543 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1544 reasonIfUnsupported,
1545 input,
1546 output,
1547 descriptor);
1548}
1549
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001550bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1551 const TensorInfo& output,
1552 const SoftmaxDescriptor& descriptor,
1553 Optional<std::string&> reasonIfUnsupported) const
1554{
1555 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1556}
1557
Mike Kelly0be3a882020-01-24 11:27:50 +00001558bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1559 const TensorInfo& output,
1560 const SpaceToBatchNdDescriptor& descriptor,
1561 Optional<std::string&> reasonIfUnsupported) const
1562{
1563 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1564 reasonIfUnsupported,
1565 input,
1566 output,
1567 descriptor);
1568}
1569
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001570bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001571 const TensorInfo& output,
1572 const SpaceToDepthDescriptor& descriptor,
1573 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001574{
1575 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1576 reasonIfUnsupported,
1577 input,
1578 output,
1579 descriptor);
1580}
1581
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001582bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001583 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1584 const ViewsDescriptor& descriptor,
1585 Optional<std::string&> reasonIfUnsupported) const
1586{
1587#if defined(ARMCOMPUTENEON_ENABLED)
1588 // Split along the last dimension, cannot use sub-tensors
1589 // as width and height of the sub-tensors do not match
1590 // the width and height of the parent tensor
1591 // in case of input with more than 2D.
1592 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1593 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1594 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1595 {
1596 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1597 reasonIfUnsupported,
1598 input,
1599 outputs,
1600 *splitAxis.begin());
1601 }
1602#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001603 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001604 for (auto output : outputs)
1605 {
1606 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1607 {
1608 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1609 return false;
1610 }
1611 }
1612 return true;
1613}
1614
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001615bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1616 const TensorInfo& output,
1617 const StackDescriptor& descriptor,
1618 Optional<std::string&> reasonIfUnsupported) const
1619{
1620 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1621 reasonIfUnsupported,
1622 inputs,
1623 output,
1624 descriptor);
1625}
1626
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001627bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1628 const TensorInfo& output,
1629 const StridedSliceDescriptor& descriptor,
1630 Optional<std::string&> reasonIfUnsupported) const
1631{
1632 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1633 reasonIfUnsupported,
1634 input,
1635 output,
1636 descriptor);
1637}
1638
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001639bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1640 const TensorInfo& input1,
1641 const TensorInfo& output,
1642 Optional<std::string&> reasonIfUnsupported) const
1643{
1644 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1645 reasonIfUnsupported,
1646 input0,
1647 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001648 output,
1649 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001650}
1651
David Monahan36e6eae2023-07-26 18:37:45 +01001652bool NeonLayerSupport::IsTileSupported(const TensorInfo& input,
1653 const TensorInfo& output,
1654 const TileDescriptor& descriptor,
1655 Optional<std::string&> reasonIfUnsupported) const
1656{
1657 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTileWorkloadValidate,
1658 reasonIfUnsupported,
1659 input,
1660 output,
1661 descriptor);
1662}
1663
Sadik Armagan581742d2019-08-12 14:11:37 +01001664bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1665 const TensorInfo& output,
1666 const TransposeConvolution2dDescriptor& descriptor,
1667 const TensorInfo& weights,
1668 const Optional<TensorInfo>& biases,
1669 Optional<std::string&> reasonIfUnsupported) const
1670{
1671 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1672 reasonIfUnsupported,
1673 input,
1674 output,
1675 descriptor,
1676 weights,
1677 biases);
1678}
1679
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001680bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1681 const TensorInfo& output,
1682 const TransposeDescriptor& descriptor,
1683 Optional<std::string&> reasonIfUnsupported) const
1684{
1685 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1686}
1687
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001688bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1689 const TensorInfo& outputStateIn,
1690 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001691 const TensorInfo& outputStateOut,
1692 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001693 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001694 const UnidirectionalSequenceLstmDescriptor& descriptor,
1695 const LstmInputParamsInfo& paramsInfo,
1696 Optional<std::string&> reasonIfUnsupported) const
1697{
Mike Kelly12994962022-04-21 11:57:09 +01001698 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1699 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1700 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1701 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1702 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1703 output.GetDataType() == armnn::DataType::QAsymmS8)
1704 {
1705 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1706 reasonIfUnsupported,
1707 input,
1708 outputStateIn,
1709 cellStateIn,
1710 outputStateOut,
1711 cellStateOut,
1712 output,
1713 descriptor,
1714 paramsInfo);
1715 }
1716 else
1717 {
1718 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1719 reasonIfUnsupported,
1720 input,
1721 outputStateIn,
1722 cellStateIn,
1723 outputStateOut,
1724 cellStateOut,
1725 output,
1726 descriptor,
1727 paramsInfo);
1728 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001729}
1730
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001731} // namespace armnn