blob: 4be5b7cb4e57bbca05144df6ccaa19f23ed7d3a7 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
Mike Kelly3ec30772023-03-08 13:47:17 +00002// Copyright © 2017-2023 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>
Sadik Armagan045f6be2020-09-10 13:37:32 +010016#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
Matteo Martincighd95e9062019-01-31 15:35:59 +000018#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010019#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar710f6642019-11-27 14:48:32 +000020#include <aclCommon/ArmComputeTensorUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010021#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000022#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010023#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010024#include "workloads/NeonArgMinMaxWorkload.hpp"
Teresa Charlin0f86ecf2022-10-13 15:47:08 +010025#include "workloads/NeonBatchMatMulWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000026#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000027#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010028#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010029#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010030#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010031#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010032#include "workloads/NeonConstantWorkload.hpp"
Matthew Bentham34336f92023-04-27 12:13:50 +000033#include "workloads/NeonConvertFp16ToFp32Workload.hpp"
34#include "workloads/NeonConvertFp32ToFp16Workload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010035#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010036#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010037#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010038#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010039#include "workloads/NeonDequantizeWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010040#include "workloads/NeonDivisionWorkload.hpp"
John Mcloughlin34c1c382023-05-17 15:08:36 +010041#include "workloads/NeonElementwiseBinaryWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010042#include "workloads/NeonExpWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010043#include "workloads/NeonFullyConnectedWorkload.hpp"
44#include "workloads/NeonFusedWorkload.hpp"
45#include "workloads/NeonGatherWorkload.hpp"
46#include "workloads/NeonGatherNdWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010047#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010048#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010049#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010050#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000051#include "workloads/NeonLogicalAndWorkload.hpp"
52#include "workloads/NeonLogicalNotWorkload.hpp"
53#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010054#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000055#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000056#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000057#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000058#include "workloads/NeonMultiplicationWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000059#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010060#include "workloads/NeonNormalizationFloatWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000061#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010062#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010063#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010064#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010065#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010066#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010067#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010068#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000069#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000070#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010071#include "workloads/NeonResizeWorkload.hpp"
Tianle Cheng21a9f332023-11-09 13:56:53 +000072#include "workloads/NeonReverseV2Workload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010073#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010074#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060075#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010076#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000077#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010078#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010079#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010080#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010081#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010082#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000083#include "workloads/NeonSubtractionWorkload.hpp"
David Monahan36e6eae2023-07-26 18:37:45 +010084#include "workloads/NeonTileWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010085#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000086#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000087#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010088#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000089#endif
90
telsoa014fcda012018-03-09 14:13:49 +000091namespace armnn
92{
telsoa014fcda012018-03-09 14:13:49 +000093
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010094namespace
arovir017ff76c52018-10-09 09:40:58 +010095{
telsoa014fcda012018-03-09 14:13:49 +000096
Cathal Corbett80f71a82022-12-20 18:25:40 +000097const TensorInfo OverrideDataType(const TensorInfo& info, Optional<DataType> type)
98{
99 if (!type)
100 {
101 return info;
102 }
103 return TensorInfo(info.GetShape(),
104 type.value(),
105 info.GetQuantizationScale(),
106 info.GetQuantizationOffset(),
107 info.IsConstant());
108}
109
Derek Lamberti901ea112019-12-10 22:07:09 +0000110template< typename ... Args>
111bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +0000112{
Jan Eilers8eb25602020-03-09 12:13:48 +0000113 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +0000114#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000115 return true;
116#else
Derek Lamberti0790dce2019-04-15 18:37:35 +0100117 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +0000118 return false;
119#endif
120}
121
telsoa01c577f2c2018-08-31 09:22:23 +0100122template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100123bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000124 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100125 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000126 Uint8Func uint8FuncPtr,
127 Params&&... params)
128{
129 return IsNeonBackendSupported(reasonIfUnsupported) &&
130 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
Teresa Charlin9145e382023-08-17 18:44:58 +0100131 dataType,
132 floatFuncPtr,
133 floatFuncPtr,
134 uint8FuncPtr,
135 &FalseFunc<>,
136 &FalseFunc<>,
137 std::forward<Params>(params)...);
telsoa014fcda012018-03-09 14:13:49 +0000138}
139
Matteo Martincighd95e9062019-01-31 15:35:59 +0000140#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000141template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100142inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000143{
144 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
145 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
146 if (!supported && reasonIfUnsupported)
147 {
arovir01085f0a42018-10-08 14:48:19 +0100148 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000149 }
150 return supported;
151}
152
153#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
154 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
155#else
156#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000157 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000158#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100159} // anonymous namespace
160
Sadik Armagan045f6be2020-09-10 13:37:32 +0100161NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
162 : m_ModelContextPtr(modelContextPtr)
163{
164}
165
166NeonLayerSupport::NeonLayerSupport()
167 : m_ModelContextPtr(nullptr)
168{
169}
170
Cathal Corbett80f71a82022-12-20 18:25:40 +0000171bool IsLayerTypeSupported(const LayerType& type,
172 const std::vector<TensorInfo>& infos,
173 const BaseDescriptor& descriptor,
174 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
175 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
176 Optional<std::string&> reasonIfUnsupported,
177 const NeonLayerSupport& support)
Cathal Corbett34b429c2021-12-24 12:24:40 +0000178{
179 switch (type)
180 {
181 case LayerType::Activation:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000182 return support.IsActivationSupported(infos[0],
183 infos[1],
184 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
185 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000186 case LayerType::Addition:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000187 return support.IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000188 case LayerType::ArgMinMax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000189 return support.IsArgMinMaxSupported(infos[0],
190 infos[1],
191 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
192 reasonIfUnsupported);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100193 case LayerType::BatchMatMul:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000194 return support.IsBatchMatMulSupported(infos[0],
195 infos[1],
196 infos[2],
197 *(PolymorphicDowncast<const BatchMatMulDescriptor*>(&descriptor)),
198 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000199 case LayerType::BatchNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000200 return support.IsBatchNormalizationSupported(infos[0],
201 infos[1],
202 infos[2],
203 infos[3],
204 infos[4],
205 infos[5],
206 *(PolymorphicDowncast<const
207 BatchNormalizationDescriptor*>(&descriptor)),
208 reasonIfUnsupported);
209 case LayerType::BatchToSpaceNd:
210 return support.IsBatchToSpaceNdSupported(infos[0],
211 infos[1],
212 *(PolymorphicDowncast<const
213 BatchToSpaceNdDescriptor*>(&descriptor)),
214 reasonIfUnsupported);
215 case LayerType::Cast:
216 return support.IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
217 case LayerType::ChannelShuffle:
218 return support.IsChannelShuffleSupported(infos[0],
219 infos[1],
220 *(PolymorphicDowncast<const
221 ChannelShuffleDescriptor*>(&descriptor)),
222 reasonIfUnsupported);
223 case LayerType::Comparison:
224 return support.IsComparisonSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000225 infos[1],
226 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000227 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000228 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000229 case LayerType::Concat:
230 {
231 std::vector<const TensorInfo*> inputInfos;
232 for (uint32_t i = 0; i < (infos.size() - 1); i++)
233 {
234 inputInfos.push_back(&infos[i]);
235 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000236 return support.IsConcatSupported(inputInfos,
237 infos[infos.size() - 1],
238 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
239 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000240 }
241 case LayerType::Constant:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000242 return support.IsConstantSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000243 case LayerType::ConvertFp16ToFp32:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000244 return support.IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000245 case LayerType::ConvertFp32ToFp16:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000246 return support.IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000247 case LayerType::Convolution2d:
248 {
249 if (infos.size() != 4)
250 {
251 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
252 "TensorInfos should be of format: {input, output, weights, biases}.");
253 }
254
255 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
256 if (infos[3] == TensorInfo())
257 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000258 return support.IsConvolution2dSupported(infos[0],
259 infos[1],
260 desc,
261 infos[2],
262 EmptyOptional(),
263 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000264 }
265 else
266 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000267 return support.IsConvolution2dSupported(infos[0],
268 infos[1],
269 desc,
270 infos[2],
271 infos[3],
272 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000273 }
274 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000275 case LayerType::Convolution3d:
276 {
277 if (infos.size() != 4)
278 {
279 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
280 "TensorInfos should be of format: {input, output, weights, biases}.");
281 }
282
283 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
284 if (infos[3] == TensorInfo())
285 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000286 return support.IsConvolution3dSupported(infos[0],
287 infos[1],
288 desc,
289 infos[2],
290 EmptyOptional(),
291 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000292 }
293 else
294 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000295 return support.IsConvolution3dSupported(infos[0],
296 infos[1],
297 desc,
298 infos[2],
299 infos[3],
300 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000301 }
302 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000303 case LayerType::DepthToSpace:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000304 return support.IsDepthToSpaceSupported(infos[0],
305 infos[1],
306 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
307 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000308 case LayerType::DepthwiseConvolution2d:
309 {
310 if (infos.size() != 4)
311 {
312 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
313 "TensorInfos should be of format: {input, output, weights, biases}.");
314 }
315
316 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
317 if (infos[3] == TensorInfo())
318 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000319 return support.IsDepthwiseConvolutionSupported(infos[0],
320 infos[1],
321 desc,
322 infos[2],
323 EmptyOptional(),
324 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000325 }
326 else
327 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000328 return support.IsDepthwiseConvolutionSupported(infos[0],
329 infos[1],
330 desc,
331 infos[2],
332 infos[3],
333 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000334 }
335 }
336 case LayerType::Dequantize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000337 return support.IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000338 case LayerType::DetectionPostProcess:
339 {
340 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
Cathal Corbett80f71a82022-12-20 18:25:40 +0000341 return support.IsDetectionPostProcessSupported(infos[0],
342 infos[1],
343 infos[2],
344 infos[3],
345 infos[4],
346 infos[5],
347 infos[6],
348 desc,
349 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000350 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000351 case LayerType::Division:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000352 return support.IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Mike Kelly3ec30772023-03-08 13:47:17 +0000353 case LayerType::ElementwiseBinary:
354 {
355 auto desc = *(PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor));
356
357 switch (desc.m_Operation)
358 {
359 case BinaryOperation::Add:
360 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
361 reasonIfUnsupported,
362 infos[0],
363 infos[1],
364 infos[2],
365 nullptr);
366 case BinaryOperation::Div:
367 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
368 reasonIfUnsupported,
369 infos[0],
370 infos[1],
371 infos[2],
372 nullptr);
373 case BinaryOperation::Maximum:
374 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
375 reasonIfUnsupported,
376 infos[0],
377 infos[1],
378 infos[2]);
379 case BinaryOperation::Minimum:
380 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
381 reasonIfUnsupported,
382 infos[0],
383 infos[1],
384 infos[2]);
385 case BinaryOperation::Mul:
386 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
387 reasonIfUnsupported,
388 infos[0],
389 infos[1],
390 infos[2],
391 nullptr);
John Mcloughlin34c1c382023-05-17 15:08:36 +0100392 case BinaryOperation::Power:
393 case BinaryOperation::SqDiff:
394 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonElementwiseBinaryWorkloadValidate,
395 reasonIfUnsupported,
396 infos[0],
397 infos[1],
398 infos[2],
399 desc,
400 nullptr);
Mike Kelly3ec30772023-03-08 13:47:17 +0000401 case BinaryOperation::Sub:
402 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
403 reasonIfUnsupported,
404 infos[0],
405 infos[1],
406 infos[2],
407 nullptr);
408 default:
409 return false;
410 }
411 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000412 case LayerType::ElementwiseUnary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000413 return support.IsElementwiseUnarySupported(infos[0],
414 infos[1],
415 *(PolymorphicDowncast<const
416 ElementwiseUnaryDescriptor*>(&descriptor)),
417 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000418 case LayerType::Fill:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000419 return support.IsFillSupported(infos[0],
420 infos[1],
421 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
422 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000423 case LayerType::Floor:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000424 return support.IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000425 case LayerType::FullyConnected:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000426 return support.IsFullyConnectedSupported(infos[0],
427 infos[1],
428 infos[2],
429 infos[3],
430 *(PolymorphicDowncast<const
431 FullyConnectedDescriptor*>(&descriptor)),
432 reasonIfUnsupported);
Teresa Charlin9145e382023-08-17 18:44:58 +0100433 case LayerType::Fused:
434 {
435 auto fusedDescriptor = *(PolymorphicDowncast<const FusedDescriptor*>(&descriptor));
436 if (fusedDescriptor.m_NumInputSlots + fusedDescriptor.m_NumOutputSlots != infos.size())
437 {
438 throw InvalidArgumentException("Invalid number of FusedLayer TensorInfos.");
439 }
440
441 std::vector<TensorInfo> inputInfos(infos.begin(), infos.begin() + fusedDescriptor.m_NumInputSlots);
442 std::vector<TensorInfo> outputInfos(infos.begin() + fusedDescriptor.m_NumInputSlots, infos.end());
443
444 return support.IsFusedSupported({inputInfos.begin(), inputInfos.end()},
445 {outputInfos.begin(), outputInfos.end()},
446 fusedDescriptor,
447 reasonIfUnsupported);
448 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000449 case LayerType::Gather:
450 return support.IsGatherSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000451 infos[1],
452 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000453 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000454 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100455 case LayerType::GatherNd:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000456 return support.IsGatherNdSupported(infos[0],
457 infos[1],
458 infos[2],
459 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000460 case LayerType::Input:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000461 return support.IsInputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000462 case LayerType::InstanceNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000463 return support.IsInstanceNormalizationSupported(infos[0],
464 infos[1],
465 *(PolymorphicDowncast<const
466 InstanceNormalizationDescriptor*>(&descriptor)),
467 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000468 case LayerType::L2Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000469 return support.IsL2NormalizationSupported(infos[0],
470 infos[1],
471 *(PolymorphicDowncast<const
472 L2NormalizationDescriptor*>(&descriptor)),
473 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000474 case LayerType::LogicalBinary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000475 return support.IsLogicalBinarySupported(infos[0],
476 infos[1],
477 infos[2],
478 *(PolymorphicDowncast<const
479 LogicalBinaryDescriptor*>(&descriptor)),
480 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000481 case LayerType::LogSoftmax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000482 return support.IsLogSoftmaxSupported(infos[0],
483 infos[1],
484 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
485 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000486 case LayerType::Lstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000487 return support.IsLstmSupported(infos[0],
488 infos[1],
489 infos[2],
490 infos[3],
491 infos[4],
492 infos[5],
493 infos[6],
494 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
495 lstmParamsInfo.value(),
496 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000497 case LayerType::Map:
498 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000499 case LayerType::Maximum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000500 return support.IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000501 case LayerType::Mean:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000502 return support.IsMeanSupported(infos[0],
503 infos[1],
504 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
505 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000506 case LayerType::MemCopy:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000507 return support.IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000508 case LayerType::MemImport:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000509 return support.IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000510 case LayerType::Merge:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000511 return support.IsMergeSupported(infos[0],
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000512 infos[1],
513 infos[2],
514 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000515 case LayerType::Minimum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000516 return support.IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000517 case LayerType::Multiplication:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000518 return support.IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000519 case LayerType::Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000520 return support.IsNormalizationSupported(infos[0],
521 infos[1],
522 *(PolymorphicDowncast<const
523 NormalizationDescriptor*>(&descriptor)),
524 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000525 case LayerType::Output:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000526 return support.IsOutputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000527 case LayerType::Pad:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000528 return support.IsPadSupported(infos[0],
529 infos[1],
530 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
531 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000532 case LayerType::Permute:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000533 return support.IsPermuteSupported(infos[0],
534 infos[1],
535 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
536 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000537 case LayerType::Pooling2d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000538 return support.IsPooling2dSupported(infos[0],
539 infos[1],
540 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
541 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100542 case LayerType::Pooling3d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000543 return support.IsPooling3dSupported(infos[0],
544 infos[1],
545 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
546 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000547 case LayerType::Prelu:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000548 return support.IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000549 case LayerType::QLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000550 return support.IsQLstmSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000551 infos[1],
552 infos[2],
553 infos[3],
554 infos[4],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000555 infos[5],
556 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
557 lstmParamsInfo.value(),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000558 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000559 case LayerType::Quantize:
560 return support.IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
561 case LayerType::QuantizedLstm:
562 return support.IsQuantizedLstmSupported(infos[0],
563 infos[1],
564 infos[2],
565 infos[3],
566 infos[4],
567 quantizedLstmParamsInfo.value(),
568 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000569 case LayerType::Rank:
570 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000571 case LayerType::Reshape:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000572 return support.IsReshapeSupported(infos[0],
573 infos[1],
574 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
575 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000576 case LayerType::Resize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000577 return support.IsResizeSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000578 infos[1],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000579 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000580 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000581 case LayerType::Reduce:
582 return support.IsReduceSupported(infos[0],
583 infos[1],
584 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
585 reasonIfUnsupported);
Tianle Cheng21a9f332023-11-09 13:56:53 +0000586 case LayerType::ReverseV2:
587 return support.IsReverseV2Supported(infos[0],
588 infos[1],
589 infos[2],
590 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000591 case LayerType::Shape:
592 return support.IsShapeSupported(infos[0],
593 infos[1],
594 reasonIfUnsupported);
595 case LayerType::Slice:
596 return support.IsSliceSupported(infos[0],
597 infos[1],
598 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
599 reasonIfUnsupported);
600 case LayerType::Softmax:
601 return support.IsSoftmaxSupported(infos[0],
602 infos[1],
603 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
604 reasonIfUnsupported);
605 case LayerType::SpaceToBatchNd:
606 return support.IsSpaceToBatchNdSupported(infos[0],
607 infos[1],
608 *(PolymorphicDowncast<const
609 SpaceToBatchNdDescriptor*>(&descriptor)),
610 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000611 case LayerType::SpaceToDepth:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000612 return support.IsSpaceToDepthSupported(infos[0],
613 infos[1],
614 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
615 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000616 case LayerType::Splitter:
617 {
618 std::vector<TensorInfo> outputInfos;
619 for (uint32_t i = 1; i < infos.size(); i++)
620 {
621 outputInfos.push_back(infos[i]);
622 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000623 return support.IsSplitterSupported(infos[0],
624 {outputInfos.begin(), outputInfos.end()},
625 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
626 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000627 }
628 case LayerType::Stack:
629 {
630 std::vector<const TensorInfo*> inputInfos;
631 for (uint32_t i = 0; i < infos.size() - 1; i++)
632 {
633 inputInfos.push_back(&infos[i]);
634 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000635 return support.IsStackSupported(inputInfos,
636 infos[infos.size() - 1],
637 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
638 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000639 }
640 case LayerType::StridedSlice:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000641 return support.IsStridedSliceSupported(infos[0],
642 infos[1],
643 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
644 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000645 case LayerType::Subtraction:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000646 return support.IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
David Monahan36e6eae2023-07-26 18:37:45 +0100647 case LayerType::Tile:
648 return support.IsTileSupported(infos[0],
649 infos[1],
650 *(PolymorphicDowncast<const TileDescriptor*>(&descriptor)),
651 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000652 case LayerType::Transpose:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000653 return support.IsTransposeSupported(infos[0],
654 infos[1],
655 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
656 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000657 case LayerType::TransposeConvolution2d:
658 {
659 if (infos.size() != 4)
660 {
661 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
662 "TensorInfos should be of format: {input, output, weights, biases}.");
663 }
664
665 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
666 if (infos[3] == TensorInfo())
667 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000668 return support.IsTransposeConvolution2dSupported(infos[0],
669 infos[1],
670 desc,
671 infos[2],
672 EmptyOptional(),
673 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000674 }
675 else
676 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000677 return support.IsTransposeConvolution2dSupported(infos[0],
678 infos[1],
679 desc,
680 infos[2],
681 infos[3],
682 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000683 }
684 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000685 case LayerType::UnidirectionalSequenceLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000686 {
687 auto desc = *(PolymorphicDowncast<const UnidirectionalSequenceLstmDescriptor*>(&descriptor));
688 return support.IsUnidirectionalSequenceLstmSupported(infos[0],
689 infos[1],
690 infos[2],
691 infos[3],
692 infos[4],
693 infos[5],
694 desc,
695 lstmParamsInfo.value(),
696 reasonIfUnsupported);
697 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000698 case LayerType::Unmap:
699 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000700 default:
701 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000702 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100703 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000704 return false;
705 }
706}
707
Cathal Corbett80f71a82022-12-20 18:25:40 +0000708bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
709 const std::vector<TensorInfo>& infos,
710 const BaseDescriptor& descriptor,
711 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
712 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
713 Optional<std::string&> reasonIfUnsupported) const
714{
715 bool isSupported = IsLayerTypeSupported(type,
716 infos,
717 descriptor,
718 lstmParamsInfo,
719 quantizedLstmParamsInfo,
720 reasonIfUnsupported,
721 *this);
722
723 // For android-nn-driver and support library, to run FP16 operations on CpuAcc we need at least v8.2
724 // architecture. If the available architecture is older than v8.2, we can check if the operator is
725 // supported by changing operator inputs & outputs to be FP32.
726 // This does not change the operator datatype in the above parsers to be FP32. We are simply reporting
727 // to the parsers if the operator can supported in ArmNN. We will then re-enter ArmNN (Network.cpp)
728 // where we will recheck IsLayerSupported() on the FP16 datatype, update the operator to be FP32,
729 // and, insert convert layers around the FP32 operator.
730 if (reasonIfUnsupported.has_value())
731 {
732 std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
733 if (!isSupported
734 && reasonIfUnsupported.value().find(checkStr) != std::string::npos)
735 {
736 std::vector<TensorInfo> newInfos;
737 for (auto info: infos)
738 {
739 newInfos.emplace_back(OverrideDataType(info, DataType::Float32));
740 }
741
742 std::string tmpString;
743 return IsLayerTypeSupported(type,
744 newInfos,
745 descriptor,
746 lstmParamsInfo,
747 quantizedLstmParamsInfo,
748 tmpString,
749 *this);
750 }
751 }
752
753 return isSupported;
754}
755
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100756bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
757 const TensorInfo& output,
758 const ActivationDescriptor& descriptor,
759 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000760{
Jan Eilers8eb25602020-03-09 12:13:48 +0000761 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100762 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
763 reasonIfUnsupported,
764 input,
765 output,
766 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000767}
768
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100769bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
770 const TensorInfo& input1,
771 const TensorInfo& output,
772 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000773{
telsoa01c577f2c2018-08-31 09:22:23 +0100774 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
775 reasonIfUnsupported,
776 input0,
777 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000778 output,
779 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000780}
781
James Conroyd47a0642019-09-17 14:22:06 +0100782bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
783 const TensorInfo& output,
784 const ArgMinMaxDescriptor& descriptor,
785 Optional<std::string&> reasonIfUnsupported) const
786{
787 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
788 reasonIfUnsupported,
789 input,
790 output,
791 descriptor);
792}
793
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100794bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
795 const TensorInfo& inputY,
796 const TensorInfo& output,
797 const BatchMatMulDescriptor& descriptor,
798 Optional<std::string&> reasonIfUnsupported) const
799{
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000800 bool isFastMathEnabled = false;
801#if defined(ARMCOMPUTENEON_ENABLED)
802 if (m_ModelContextPtr)
803 {
804 if (m_ModelContextPtr.get() != nullptr)
805 {
806 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
807 if (modelOptions)
808 {
809 isFastMathEnabled = modelOptions->IsFastMathEnabled();
810 }
811 }
812 }
813#endif
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100814 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
815 reasonIfUnsupported,
816 inputX,
817 inputY,
818 output,
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000819 descriptor,
820 isFastMathEnabled,
821 nullptr);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100822}
823
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100824bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
825 const TensorInfo& output,
826 const TensorInfo& mean,
827 const TensorInfo& var,
828 const TensorInfo& beta,
829 const TensorInfo& gamma,
830 const BatchNormalizationDescriptor& descriptor,
831 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000832{
telsoa01c577f2c2018-08-31 09:22:23 +0100833 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
834 reasonIfUnsupported,
835 input,
836 output,
837 mean,
838 var,
839 beta,
840 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000841 descriptor,
842 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000843}
844
Mike Kelly56858022020-01-27 12:14:47 +0000845bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
846 const TensorInfo& output,
847 const BatchToSpaceNdDescriptor& descriptor,
848 Optional<std::string&> reasonIfUnsupported) const
849{
850 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
851 reasonIfUnsupported,
852 input,
853 output,
854 descriptor);
855}
856
Sadik Armagan48f011e2021-04-21 10:50:34 +0100857bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
858 const TensorInfo& output,
859 Optional<std::string&> reasonIfUnsupported) const
860{
861 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
862 reasonIfUnsupported,
863 input,
864 output);
865}
866
Teresa Charline89dd692021-09-01 16:30:34 +0100867bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
868 const TensorInfo& output,
869 const ChannelShuffleDescriptor& descriptor,
870 Optional<std::string&> reasonIfUnsupported) const
871{
872 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
873 reasonIfUnsupported,
874 input,
875 output,
876 descriptor);
877}
878
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100879bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
880 const TensorInfo& input1,
881 const TensorInfo& output,
882 const ComparisonDescriptor& descriptor,
883 Optional<std::string&> reasonIfUnsupported) const
884{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100885
Teresa Charlincedd34f2020-03-30 11:17:30 +0100886 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
887 reasonIfUnsupported,
888 input0,
889 input1,
890 output,
891 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100892}
893
Jim Flynn906f9462019-05-10 13:55:21 +0100894bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
895 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000896 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100897 Optional<std::string&> reasonIfUnsupported) const
898{
Jim Flynne242f2d2019-05-22 14:24:13 +0100899 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
900 {
901 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
902 return false;
903 }
904
905 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
906 if(concatInnerAxis < 3) // Width, height, or channels
907 {
908 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
909 reasonIfUnsupported,
910 inputs,
911 output,
912 descriptor);
913 }
914 else if (concatInnerAxis == 3)
915 {
916 for (auto& input : inputs)
917 {
918 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
919 {
920 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
921 return false;
922 }
923 }
924 return true; // Sub-tensors support concat along batch
925 }
926 else // > 4 dimensions not supported.
927 {
928 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
929 return false;
930 }
Jim Flynn906f9462019-05-10 13:55:21 +0100931}
932
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100933bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
934 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000935{
Mike Kelly0886ac42020-04-27 09:55:40 +0100936 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
937 reasonIfUnsupported,
938 output);
telsoa014fcda012018-03-09 14:13:49 +0000939}
940
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100941bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
942 const TensorInfo& output,
943 Optional<std::string&> reasonIfUnsupported) const
944{
Matthew Bentham34336f92023-04-27 12:13:50 +0000945 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp16ToFp32WorkloadValidate,
946 reasonIfUnsupported,
947 input,
948 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100949}
950
951bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
952 const TensorInfo& output,
953 Optional<std::string&> reasonIfUnsupported) const
954{
Matthew Bentham34336f92023-04-27 12:13:50 +0000955 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp32ToFp16WorkloadValidate,
956 reasonIfUnsupported,
957 input,
958 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100959}
960
961bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
962 const TensorInfo& output,
963 const Convolution2dDescriptor& descriptor,
964 const TensorInfo& weights,
965 const Optional<TensorInfo>& biases,
966 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000967{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100968 bool isFastMathEnabled = false;
969#if defined(ARMCOMPUTENEON_ENABLED)
970 if (m_ModelContextPtr)
971 {
972 if (m_ModelContextPtr.get() != nullptr)
973 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100974 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100975 if (modelOptions)
976 {
977 isFastMathEnabled = modelOptions->IsFastMathEnabled();
978 }
979 }
980 }
981#endif
982
surmeh013537c2c2018-05-18 16:31:43 +0100983 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
984 reasonIfUnsupported,
985 input,
986 output,
987 descriptor,
988 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100989 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000990 isFastMathEnabled,
991 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000992}
993
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100994bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
995 const TensorInfo& output,
996 const Convolution3dDescriptor& descriptor,
997 const TensorInfo& weights,
998 const Optional<TensorInfo>& biases,
999 Optional<std::string&> reasonIfUnsupported) const
1000{
1001 bool isFastMathEnabled = false;
1002#if defined(ARMCOMPUTENEON_ENABLED)
1003 if (m_ModelContextPtr)
1004 {
1005 if (m_ModelContextPtr.get() != nullptr)
1006 {
1007 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
1008 if (modelOptions)
1009 {
1010 isFastMathEnabled = modelOptions->IsFastMathEnabled();
1011 }
1012 }
1013 }
1014#endif
1015
1016 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
1017 reasonIfUnsupported,
1018 input,
1019 output,
1020 descriptor,
1021 weights,
1022 biases,
1023 isFastMathEnabled,
1024 nullptr);
1025}
1026
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +01001027bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
1028 const TensorInfo& output,
1029 const DepthToSpaceDescriptor& descriptor,
1030 Optional<std::string&> reasonIfUnsupported) const
1031{
1032 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
1033 reasonIfUnsupported,
1034 input,
1035 output,
1036 descriptor);
1037}
1038
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001039bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
1040 const TensorInfo& output,
1041 const DepthwiseConvolution2dDescriptor& descriptor,
1042 const TensorInfo& weights,
1043 const Optional<TensorInfo>& biases,
1044 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001045{
telsoa01c577f2c2018-08-31 09:22:23 +01001046 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1047 reasonIfUnsupported,
1048 input,
1049 output,
1050 descriptor,
1051 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001052 biases,
1053 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001054}
1055
Narumol Prangnawarat01961a72019-05-30 16:47:12 +01001056bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
1057 const TensorInfo& output,
1058 Optional<std::string&> reasonIfUnsupported) const
1059{
1060 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
1061 reasonIfUnsupported,
1062 input,
1063 output);
1064}
1065
Pablo Tellof0bd6832019-04-26 17:58:13 +01001066bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
1067 const TensorInfo& output,
1068 const DepthwiseConvolution2dDescriptor& descriptor,
1069 const TensorInfo& weights,
1070 const Optional<TensorInfo>& biases,
1071 Optional<std::string&> reasonIfUnsupported) const
1072{
1073 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1074 reasonIfUnsupported,
1075 input,
1076 output,
1077 descriptor,
1078 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001079 biases,
1080 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +01001081}
1082
josh minor4a3c6102020-01-06 16:40:46 -06001083bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
1084 const TensorInfo& output,
1085 const ElementwiseUnaryDescriptor& descriptor,
1086 Optional<std::string&> reasonIfUnsupported) const
1087{
Derek Lambertic77874a2020-04-28 13:34:56 +01001088 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -06001089 {
Derek Lambertic77874a2020-04-28 13:34:56 +01001090 case UnaryOperation::Abs:
1091 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
1092 reasonIfUnsupported,
1093 input,
1094 output);
1095 case UnaryOperation::Exp:
1096 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
1097 reasonIfUnsupported,
1098 input,
1099 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +01001100 case UnaryOperation::LogicalNot:
1101 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
1102 reasonIfUnsupported,
1103 input,
1104 output);
1105 case UnaryOperation::Log:
1106 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
1107 reasonIfUnsupported,
1108 input,
1109 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001110 case UnaryOperation::Neg:
1111 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
1112 reasonIfUnsupported,
1113 input,
1114 output);
1115 case UnaryOperation::Rsqrt:
1116 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
1117 reasonIfUnsupported,
1118 input,
1119 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +00001120 case UnaryOperation::Sin:
1121 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
1122 reasonIfUnsupported,
1123 input,
1124 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +01001125 case UnaryOperation::Sqrt:
1126 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
1127 reasonIfUnsupported,
1128 input,
1129 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001130 default:
1131 return false;
josh minor4a3c6102020-01-06 16:40:46 -06001132 }
josh minor4a3c6102020-01-06 16:40:46 -06001133}
1134
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001135bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
1136 const TensorInfo& output,
1137 const FillDescriptor& descriptor,
1138 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +01001139{
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001140 armnn::IgnoreUnused(input);
1141 armnn::IgnoreUnused(output);
1142 armnn::IgnoreUnused(descriptor);
1143
1144 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +01001145}
1146
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001147bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
1148 const TensorInfo& output,
1149 Optional<std::string&> reasonIfUnsupported) const
1150{
Jan Eilers8eb25602020-03-09 12:13:48 +00001151 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001152 return IsNeonBackendSupported(reasonIfUnsupported) &&
1153 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1154 input.GetDataType(),
1155 &FalseFuncF16<>,
1156 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001157 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001158 &FalseFuncI32<>,
1159 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001160}
1161
1162bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1163 const TensorInfo& output,
1164 const TensorInfo& weights,
1165 const TensorInfo& biases,
1166 const FullyConnectedDescriptor& descriptor,
1167 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001168{
telsoa01c577f2c2018-08-31 09:22:23 +01001169 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1170 reasonIfUnsupported,
1171 input,
1172 output,
1173 weights,
1174 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001175 descriptor,
1176 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001177}
1178
Teresa Charlin9145e382023-08-17 18:44:58 +01001179bool NeonLayerSupport::IsFusedSupported(const std::vector<std::reference_wrapper<TensorInfo>>& inputs,
1180 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1181 const FusedDescriptor& descriptor,
1182 Optional<std::string&> reasonIfUnsupported) const
1183{
1184 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFusedWorkloadValidate,
1185 reasonIfUnsupported,
1186 inputs,
1187 outputs,
1188 descriptor,
1189 nullptr);
1190}
1191
Teresa Charlinf540eb82020-04-10 19:24:55 +01001192bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1193 const TensorInfo& input1,
1194 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001195 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001196 Optional<std::string&> reasonIfUnsupported) const
1197{
1198 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1199 reasonIfUnsupported,
1200 input0,
1201 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001202 output,
1203 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001204}
1205
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001206bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1207 const TensorInfo& input1,
1208 const TensorInfo& output,
1209 Optional<std::string&> reasonIfUnsupported) const
1210{
1211 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1212 reasonIfUnsupported,
1213 input0,
1214 input1,
1215 output);
1216}
1217
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001218bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1219 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001220{
Derek Lamberti901ea112019-12-10 22:07:09 +00001221 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001222}
1223
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001224bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1225 const TensorInfo& output,
1226 const InstanceNormalizationDescriptor& descriptor,
1227 Optional<std::string&> reasonIfUnsupported) const
1228{
1229 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1230 reasonIfUnsupported,
1231 input,
1232 output,
1233 descriptor);
1234}
1235
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001236bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1237 const TensorInfo& output,
1238 const L2NormalizationDescriptor& descriptor,
1239 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001240{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001241 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001242}
1243
James Conroy177df1e2020-11-13 10:18:51 +00001244bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1245 const TensorInfo& input1,
1246 const TensorInfo& output,
1247 const LogicalBinaryDescriptor& descriptor,
1248 Optional<std::string&> reasonIfUnsupported) const
1249{
1250 switch(descriptor.m_Operation)
1251 {
1252 case LogicalBinaryOperation::LogicalAnd:
1253 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1254 reasonIfUnsupported,
1255 input0,
1256 input1,
1257 output);
1258 case LogicalBinaryOperation::LogicalOr:
1259 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1260 reasonIfUnsupported,
1261 input0,
1262 input1,
1263 output);
1264 default:
1265 return false;
1266 }
1267}
1268
Keith Davis69e653f2020-07-02 11:49:26 +01001269bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1270 const TensorInfo& output,
1271 const LogSoftmaxDescriptor& descriptor,
1272 Optional<std::string&> reasonIfUnsupported) const
1273{
1274 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1275}
1276
Jan Eilersad5293a2019-07-08 09:57:55 +01001277bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1278 const TensorInfo& outputStateIn,
1279 const TensorInfo& cellStateIn,
1280 const TensorInfo& scratchBuffer,
1281 const TensorInfo& outputStateOut,
1282 const TensorInfo& cellStateOut,
1283 const TensorInfo& output,
1284 const LstmDescriptor& descriptor,
1285 const LstmInputParamsInfo& paramsInfo,
1286 Optional<std::string&> reasonIfUnsupported) const
1287{
1288 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1289 reasonIfUnsupported,
1290 input,
1291 outputStateIn,
1292 cellStateIn,
1293 scratchBuffer,
1294 outputStateOut,
1295 cellStateOut,
1296 output,
1297 descriptor,
1298 paramsInfo);
1299}
1300
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001301bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1302 const TensorInfo& input1,
1303 const TensorInfo& output,
1304 Optional<std::string&> reasonIfUnsupported) const
1305{
1306 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1307 reasonIfUnsupported,
1308 input0,
1309 input1,
1310 output);
1311}
1312
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001313bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1314 const TensorInfo& output,
1315 const MeanDescriptor& descriptor,
1316 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001317{
Matthew Benthamfd899962018-12-31 15:49:42 +00001318 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1319 reasonIfUnsupported,
1320 input,
1321 output,
1322 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001323}
1324
Conor Kennedy54b21692019-01-09 07:57:38 +00001325bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1326 const TensorInfo& input1,
1327 const TensorInfo& output,
1328 Optional<std::string&> reasonIfUnsupported) const
1329{
1330 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1331 reasonIfUnsupported,
1332 input0,
1333 input1,
1334 output);
1335}
1336
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001337bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1338 const TensorInfo& input1,
1339 const TensorInfo& output,
1340 Optional<std::string&> reasonIfUnsupported) const
1341{
1342 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1343 reasonIfUnsupported,
1344 input0,
1345 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001346 output,
1347 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001348}
1349
Pablo Telloe61f0712020-01-23 10:37:17 +00001350bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1351 const TensorInfo& input1,
1352 const TensorInfo& output,
1353 Optional<std::string&> reasonIfUnsupported) const
1354{
1355 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1356 reasonIfUnsupported,
1357 input0,
1358 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001359 output,
1360 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001361}
1362
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001363bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1364 const TensorInfo& output,
1365 const NormalizationDescriptor& descriptor,
1366 Optional<std::string&> reasonIfUnsupported) const
1367{
1368 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1369 reasonIfUnsupported,
1370 input,
1371 output,
1372 descriptor);
1373}
1374
1375bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1376 Optional<std::string&> reasonIfUnsupported) const
1377{
Derek Lamberti901ea112019-12-10 22:07:09 +00001378 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001379}
1380
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001381bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1382 const TensorInfo& output,
1383 const PadDescriptor& descriptor,
1384 Optional<std::string&> reasonIfUnsupported) const
1385{
1386 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1387 reasonIfUnsupported,
1388 input,
1389 output,
1390 descriptor);
1391}
1392
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001393bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1394 const TensorInfo& output,
1395 const PermuteDescriptor& descriptor,
1396 Optional<std::string&> reasonIfUnsupported) const
1397{
1398 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001399}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001400
1401bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1402 const TensorInfo& output,
1403 const Pooling2dDescriptor& descriptor,
1404 Optional<std::string&> reasonIfUnsupported) const
1405{
1406 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1407}
1408
Ryan OShea19e79422022-05-04 00:38:03 +01001409bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1410 const TensorInfo& output,
1411 const Pooling3dDescriptor& descriptor,
1412 Optional<std::string&> reasonIfUnsupported) const
1413{
1414 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1415}
1416
Nikhil Raj9b461482019-07-03 15:58:31 +01001417bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1418 const armnn::TensorInfo &alpha,
1419 const armnn::TensorInfo &output,
1420 armnn::Optional<std::string &> reasonIfUnsupported) const
1421{
1422 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1423}
1424
James Conroycc340932020-05-12 18:08:52 +01001425bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1426 const TensorInfo& previousOutputIn,
1427 const TensorInfo& previousCellStateIn,
1428 const TensorInfo& outputStateOut,
1429 const TensorInfo& cellStateOut,
1430 const TensorInfo& output,
1431 const QLstmDescriptor& descriptor,
1432 const LstmInputParamsInfo& paramsInfo,
1433 Optional<std::string&> reasonIfUnsupported) const
1434{
1435 // Check required here in order to pass IsLayerSupported for datatypes tests
1436 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1437 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1438 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1439 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1440 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1441 output.GetDataType() == armnn::DataType::QAsymmS8)
1442 {
1443 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1444 reasonIfUnsupported,
1445 input,
1446 previousCellStateIn,
1447 previousOutputIn,
1448 cellStateOut,
1449 outputStateOut,
1450 output,
1451 descriptor,
1452 paramsInfo);
1453 }
1454 else
1455 {
1456 return false;
1457 }
1458}
1459
Sadik Armaganfabc2892019-05-31 09:05:11 +01001460bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1461 const TensorInfo& output,
1462 Optional<std::string&> reasonIfUnsupported) const
1463{
1464 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1465 reasonIfUnsupported,
1466 input,
1467 output);
1468}
1469
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001470bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1471 const TensorInfo& cellStateIn,
1472 const TensorInfo& outputStateIn,
1473 const TensorInfo& cellStateOut,
1474 const TensorInfo& outputStateOut,
1475 const QuantizedLstmInputParamsInfo& paramsInfo,
1476 Optional<std::string&> reasonIfUnsupported) const
1477{
1478 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1479 reasonIfUnsupported,
1480 input,
1481 cellStateIn,
1482 outputStateIn,
1483 cellStateOut,
1484 outputStateOut,
1485 paramsInfo);
1486}
1487
Sadik Armagana2747482021-02-09 10:28:54 +00001488bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1489 const TensorInfo& output,
1490 const ReduceDescriptor& descriptor,
1491 Optional<std::string&> reasonIfUnsupported) const
1492{
1493 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1494 reasonIfUnsupported,
1495 input,
1496 output,
1497 descriptor);
1498}
1499
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001500bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001501 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001502 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001503 Optional<std::string&> reasonIfUnsupported) const
1504{
Jan Eilers8eb25602020-03-09 12:13:48 +00001505 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001506 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1507 reasonIfUnsupported,
1508 input,
1509 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001510}
1511
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001512bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1513 const TensorInfo& output,
1514 const ResizeDescriptor& descriptor,
1515 Optional<std::string&> reasonIfUnsupported) const
1516{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001517 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1518 reasonIfUnsupported,
1519 input,
1520 output,
1521 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001522}
1523
Tianle Cheng21a9f332023-11-09 13:56:53 +00001524bool NeonLayerSupport::IsReverseV2Supported(const armnn::TensorInfo &input,
1525 const armnn::TensorInfo &axis,
1526 const armnn::TensorInfo &output,
1527 Optional<std::string &> reasonIfUnsupported) const
1528{
1529 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReverseV2WorkloadValidate,
1530 reasonIfUnsupported,
1531 input,
1532 axis,
1533 output);
1534}
1535
josh minor036f02d2019-11-15 14:53:22 -06001536bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1537 const TensorInfo& output,
1538 const SliceDescriptor& descriptor,
1539 Optional<std::string&> reasonIfUnsupported) const
1540{
1541 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1542 reasonIfUnsupported,
1543 input,
1544 output,
1545 descriptor);
1546}
1547
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001548bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1549 const TensorInfo& output,
1550 const SoftmaxDescriptor& descriptor,
1551 Optional<std::string&> reasonIfUnsupported) const
1552{
1553 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1554}
1555
Mike Kelly0be3a882020-01-24 11:27:50 +00001556bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1557 const TensorInfo& output,
1558 const SpaceToBatchNdDescriptor& descriptor,
1559 Optional<std::string&> reasonIfUnsupported) const
1560{
1561 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1562 reasonIfUnsupported,
1563 input,
1564 output,
1565 descriptor);
1566}
1567
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001568bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001569 const TensorInfo& output,
1570 const SpaceToDepthDescriptor& descriptor,
1571 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001572{
1573 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1574 reasonIfUnsupported,
1575 input,
1576 output,
1577 descriptor);
1578}
1579
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001580bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001581 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1582 const ViewsDescriptor& descriptor,
1583 Optional<std::string&> reasonIfUnsupported) const
1584{
1585#if defined(ARMCOMPUTENEON_ENABLED)
1586 // Split along the last dimension, cannot use sub-tensors
1587 // as width and height of the sub-tensors do not match
1588 // the width and height of the parent tensor
1589 // in case of input with more than 2D.
1590 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1591 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1592 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1593 {
1594 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1595 reasonIfUnsupported,
1596 input,
1597 outputs,
1598 *splitAxis.begin());
1599 }
1600#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001601 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001602 for (auto output : outputs)
1603 {
1604 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1605 {
1606 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1607 return false;
1608 }
1609 }
1610 return true;
1611}
1612
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001613bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1614 const TensorInfo& output,
1615 const StackDescriptor& descriptor,
1616 Optional<std::string&> reasonIfUnsupported) const
1617{
1618 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1619 reasonIfUnsupported,
1620 inputs,
1621 output,
1622 descriptor);
1623}
1624
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001625bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1626 const TensorInfo& output,
1627 const StridedSliceDescriptor& descriptor,
1628 Optional<std::string&> reasonIfUnsupported) const
1629{
1630 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1631 reasonIfUnsupported,
1632 input,
1633 output,
1634 descriptor);
1635}
1636
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001637bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1638 const TensorInfo& input1,
1639 const TensorInfo& output,
1640 Optional<std::string&> reasonIfUnsupported) const
1641{
1642 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1643 reasonIfUnsupported,
1644 input0,
1645 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001646 output,
1647 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001648}
1649
David Monahan36e6eae2023-07-26 18:37:45 +01001650bool NeonLayerSupport::IsTileSupported(const TensorInfo& input,
1651 const TensorInfo& output,
1652 const TileDescriptor& descriptor,
1653 Optional<std::string&> reasonIfUnsupported) const
1654{
1655 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTileWorkloadValidate,
1656 reasonIfUnsupported,
1657 input,
1658 output,
1659 descriptor);
1660}
1661
Sadik Armagan581742d2019-08-12 14:11:37 +01001662bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1663 const TensorInfo& output,
1664 const TransposeConvolution2dDescriptor& descriptor,
1665 const TensorInfo& weights,
1666 const Optional<TensorInfo>& biases,
1667 Optional<std::string&> reasonIfUnsupported) const
1668{
1669 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1670 reasonIfUnsupported,
1671 input,
1672 output,
1673 descriptor,
1674 weights,
1675 biases);
1676}
1677
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001678bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1679 const TensorInfo& output,
1680 const TransposeDescriptor& descriptor,
1681 Optional<std::string&> reasonIfUnsupported) const
1682{
1683 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1684}
1685
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001686bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1687 const TensorInfo& outputStateIn,
1688 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001689 const TensorInfo& outputStateOut,
1690 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001691 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001692 const UnidirectionalSequenceLstmDescriptor& descriptor,
1693 const LstmInputParamsInfo& paramsInfo,
1694 Optional<std::string&> reasonIfUnsupported) const
1695{
Mike Kelly12994962022-04-21 11:57:09 +01001696 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1697 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1698 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1699 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1700 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1701 output.GetDataType() == armnn::DataType::QAsymmS8)
1702 {
1703 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1704 reasonIfUnsupported,
1705 input,
1706 outputStateIn,
1707 cellStateIn,
1708 outputStateOut,
1709 cellStateOut,
1710 output,
1711 descriptor,
1712 paramsInfo);
1713 }
1714 else
1715 {
1716 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1717 reasonIfUnsupported,
1718 input,
1719 outputStateIn,
1720 cellStateIn,
1721 outputStateOut,
1722 cellStateOut,
1723 output,
1724 descriptor,
1725 paramsInfo);
1726 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001727}
1728
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001729} // namespace armnn