blob: 7f311d8684c17f0851e52efda17c5a1dd1557fd2 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
Teresa Charlin52664732020-06-29 16:27:03 +01002// Copyright © 2017 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"
David Beck3e9e1152018-10-17 14:17:50 +01007#include "NeonBackendId.hpp"
Sadik Armagan045f6be2020-09-10 13:37:32 +01008#include "NeonBackendModelContext.hpp"
telsoa014fcda012018-03-09 14:13:49 +00009
Derek Lambertic77874a2020-04-28 13:34:56 +010010#include <armnn/Exceptions.hpp>
telsoa014fcda012018-03-09 14:13:49 +000011#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010012#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000013#include <armnn/BackendRegistry.hpp>
telsoa014fcda012018-03-09 14:13:49 +000014
Matteo Martincighc601aa62019-10-29 15:03:22 +000015#include <InternalTypes.hpp>
16#include <LayerSupportCommon.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000017#include <armnn/utility/IgnoreUnused.hpp>
Sadik Armagan045f6be2020-09-10 13:37:32 +010018#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000019
Matteo Martincighd95e9062019-01-31 15:35:59 +000020#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010021#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar710f6642019-11-27 14:48:32 +000022#include <aclCommon/ArmComputeTensorUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010023#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000024#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010025#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010026#include "workloads/NeonArgMinMaxWorkload.hpp"
Teresa Charlin0f86ecf2022-10-13 15:47:08 +010027#include "workloads/NeonBatchMatMulWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000028#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000029#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010030#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010031#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010032#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010033#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010034#include "workloads/NeonConstantWorkload.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 Charline89dd692021-09-01 16:30:34 +010040#include "workloads/NeonExpWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010041#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010042#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010043#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010044#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000045#include "workloads/NeonLogicalAndWorkload.hpp"
46#include "workloads/NeonLogicalNotWorkload.hpp"
47#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010048#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000049#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000050#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000051#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000052#include "workloads/NeonMultiplicationWorkload.hpp"
Pablo Telloe61f0712020-01-23 10:37:17 +000053#include "workloads/NeonDivisionWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000054#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010055#include "workloads/NeonNormalizationFloatWorkload.hpp"
56#include "workloads/NeonFullyConnectedWorkload.hpp"
Teresa Charlinf540eb82020-04-10 19:24:55 +010057#include "workloads/NeonGatherWorkload.hpp"
Teresa Charlinbd22c7d2022-04-26 18:14:12 +010058#include "workloads/NeonGatherNdWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000059#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010060#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010061#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010062#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010063#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010064#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010065#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010066#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000067#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000068#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010069#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010070#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010071#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060072#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010073#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000074#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010075#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010076#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010077#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010078#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010079#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000080#include "workloads/NeonSubtractionWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010081#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000082#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000083#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010084#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000085#endif
86
telsoa014fcda012018-03-09 14:13:49 +000087namespace armnn
88{
telsoa014fcda012018-03-09 14:13:49 +000089
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010090namespace
arovir017ff76c52018-10-09 09:40:58 +010091{
telsoa014fcda012018-03-09 14:13:49 +000092
Derek Lamberti901ea112019-12-10 22:07:09 +000093template< typename ... Args>
94bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +000095{
Jan Eilers8eb25602020-03-09 12:13:48 +000096 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +000097#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000098 return true;
99#else
Derek Lamberti0790dce2019-04-15 18:37:35 +0100100 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +0000101 return false;
102#endif
103}
104
telsoa01c577f2c2018-08-31 09:22:23 +0100105template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100106bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000107 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100108 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000109 Uint8Func uint8FuncPtr,
110 Params&&... params)
111{
112 return IsNeonBackendSupported(reasonIfUnsupported) &&
113 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
114 dataType,
115 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +0100116 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000117 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +0000118 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000119 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +0000120 std::forward<Params>(params)...);
121}
122
Matteo Martincighd95e9062019-01-31 15:35:59 +0000123#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000124template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100125inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000126{
127 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
128 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
129 if (!supported && reasonIfUnsupported)
130 {
arovir01085f0a42018-10-08 14:48:19 +0100131 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000132 }
133 return supported;
134}
135
136#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
137 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
138#else
139#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000140 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000141#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100142} // anonymous namespace
143
Sadik Armagan045f6be2020-09-10 13:37:32 +0100144NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
145 : m_ModelContextPtr(modelContextPtr)
146{
147}
148
149NeonLayerSupport::NeonLayerSupport()
150 : m_ModelContextPtr(nullptr)
151{
152}
153
Cathal Corbett34b429c2021-12-24 12:24:40 +0000154bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
155 const std::vector<TensorInfo>& infos,
156 const BaseDescriptor& descriptor,
157 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
158 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
159 Optional<std::string&> reasonIfUnsupported) const
160{
161 switch (type)
162 {
163 case LayerType::Activation:
164 return IsActivationSupported(infos[0],
165 infos[1],
166 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
167 reasonIfUnsupported);
168 case LayerType::Addition:
169 return IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
170 case LayerType::ArgMinMax:
171 return IsArgMinMaxSupported(infos[0],
172 infos[1],
173 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
174 reasonIfUnsupported);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100175 case LayerType::BatchMatMul:
176 return IsBatchMatMulSupported(infos[0],
177 infos[1],
178 infos[2],
179 *(PolymorphicDowncast<const BatchMatMulDescriptor*>(&descriptor)),
180 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000181 case LayerType::BatchNormalization:
182 return IsBatchNormalizationSupported(infos[0],
183 infos[1],
184 infos[2],
185 infos[3],
186 infos[4],
187 infos[5],
188 *(PolymorphicDowncast<const BatchNormalizationDescriptor*>
189 (&descriptor)),
190 reasonIfUnsupported);
191 case LayerType::BatchToSpaceNd:
192 return IsBatchToSpaceNdSupported(infos[0],
193 infos[1],
194 *(PolymorphicDowncast<const BatchToSpaceNdDescriptor*>(&descriptor)),
195 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000196 case LayerType::Cast:
197 return IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
198 case LayerType::ChannelShuffle:
199 return IsChannelShuffleSupported(infos[0],
200 infos[1],
201 *(PolymorphicDowncast<const ChannelShuffleDescriptor*>(&descriptor)),
202 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000203 case LayerType::Comparison:
204 return IsComparisonSupported(infos[0],
205 infos[1],
206 infos[2],
207 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
208 reasonIfUnsupported);
209 case LayerType::Concat:
210 {
211 std::vector<const TensorInfo*> inputInfos;
212 for (uint32_t i = 0; i < (infos.size() - 1); i++)
213 {
214 inputInfos.push_back(&infos[i]);
215 }
216 return IsConcatSupported(inputInfos,
217 infos[infos.size() - 1],
218 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
219 reasonIfUnsupported);
220 }
221 case LayerType::Constant:
222 return IsConstantSupported(infos[0], reasonIfUnsupported);
223 case LayerType::ConvertBf16ToFp32:
224 return IsConvertBf16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
225 case LayerType::ConvertFp16ToFp32:
226 return IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
227 case LayerType::ConvertFp32ToBf16:
228 return IsConvertFp32ToBf16Supported(infos[0], infos[1], reasonIfUnsupported);
229 case LayerType::ConvertFp32ToFp16:
230 return IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
231 case LayerType::Convolution2d:
232 {
233 if (infos.size() != 4)
234 {
235 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
236 "TensorInfos should be of format: {input, output, weights, biases}.");
237 }
238
239 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
240 if (infos[3] == TensorInfo())
241 {
242 return IsConvolution2dSupported(infos[0],
243 infos[1],
244 desc,
245 infos[2],
246 EmptyOptional(),
247 reasonIfUnsupported);
248 }
249 else
250 {
251 return IsConvolution2dSupported(infos[0],
252 infos[1],
253 desc,
254 infos[2],
255 infos[3],
256 reasonIfUnsupported);
257 }
258 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000259 case LayerType::Convolution3d:
260 {
261 if (infos.size() != 4)
262 {
263 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
264 "TensorInfos should be of format: {input, output, weights, biases}.");
265 }
266
267 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
268 if (infos[3] == TensorInfo())
269 {
270 return IsConvolution3dSupported(infos[0],
271 infos[1],
272 desc,
273 infos[2],
274 EmptyOptional(),
275 reasonIfUnsupported);
276 }
277 else
278 {
279 return IsConvolution3dSupported(infos[0],
280 infos[1],
281 desc,
282 infos[2],
283 infos[3],
284 reasonIfUnsupported);
285 }
286 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000287 case LayerType::DepthToSpace:
288 return IsDepthToSpaceSupported(infos[0],
289 infos[1],
290 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
291 reasonIfUnsupported);
292 case LayerType::DepthwiseConvolution2d:
293 {
294 if (infos.size() != 4)
295 {
296 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
297 "TensorInfos should be of format: {input, output, weights, biases}.");
298 }
299
300 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
301 if (infos[3] == TensorInfo())
302 {
303 return IsDepthwiseConvolutionSupported(infos[0],
304 infos[1],
305 desc,
306 infos[2],
307 EmptyOptional(),
308 reasonIfUnsupported);
309 }
310 else
311 {
312 return IsDepthwiseConvolutionSupported(infos[0],
313 infos[1],
314 desc,
315 infos[2],
316 infos[3],
317 reasonIfUnsupported);
318 }
319 }
320 case LayerType::Dequantize:
321 return IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000322 case LayerType::DetectionPostProcess:
323 {
324 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
325 return LayerSupportBase::IsDetectionPostProcessSupported(infos[0],
326 infos[1],
327 infos[2],
328 infos[3],
329 infos[4],
330 infos[5],
331 infos[6],
332 desc,
333 reasonIfUnsupported);
334 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000335 case LayerType::Division:
336 return IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
337 case LayerType::ElementwiseUnary:
338 return IsElementwiseUnarySupported(infos[0],
339 infos[1],
340 *(PolymorphicDowncast<const ElementwiseUnaryDescriptor*>(&descriptor)),
341 reasonIfUnsupported);
342 case LayerType::Fill:
343 return IsFillSupported(infos[0],
344 infos[1],
345 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
346 reasonIfUnsupported);
347 case LayerType::Floor:
348 return IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
349 case LayerType::FullyConnected:
350 return IsFullyConnectedSupported(infos[0],
351 infos[1],
352 infos[2],
353 infos[3],
354 *(PolymorphicDowncast<const FullyConnectedDescriptor*>(&descriptor)),
355 reasonIfUnsupported);
356 case LayerType::Gather:
357 return IsGatherSupported(infos[0],
358 infos[1],
359 infos[2],
360 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
361 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100362 case LayerType::GatherNd:
363 return IsGatherNdSupported(infos[0],
364 infos[1],
365 infos[2],
366 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000367 case LayerType::Input:
368 return IsInputSupported(infos[0], reasonIfUnsupported);
369 case LayerType::InstanceNormalization:
370 return IsInstanceNormalizationSupported(infos[0],
371 infos[1],
372 *(PolymorphicDowncast<const InstanceNormalizationDescriptor*>
373 (&descriptor)),
374 reasonIfUnsupported);
375 case LayerType::L2Normalization:
376 return IsL2NormalizationSupported(infos[0],
377 infos[1],
378 *(PolymorphicDowncast<const L2NormalizationDescriptor*>(&descriptor)),
379 reasonIfUnsupported);
380 case LayerType::LogicalBinary:
381 return IsLogicalBinarySupported(infos[0],
382 infos[1],
383 infos[2],
384 *(PolymorphicDowncast<const LogicalBinaryDescriptor*>(&descriptor)),
385 reasonIfUnsupported);
386 case LayerType::LogSoftmax:
387 return IsLogSoftmaxSupported(infos[0],
388 infos[1],
389 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
390 reasonIfUnsupported);
391 case LayerType::Lstm:
392 return IsLstmSupported(infos[0],
393 infos[1],
394 infos[2],
395 infos[3],
396 infos[4],
397 infos[5],
398 infos[6],
399 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
400 lstmParamsInfo.value(),
401 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000402 case LayerType::Map:
403 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000404 case LayerType::Maximum:
405 return IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
406 case LayerType::Mean:
407 return IsMeanSupported(infos[0],
408 infos[1],
409 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
410 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000411 case LayerType::MemCopy:
412 return LayerSupportBase::IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
413 case LayerType::MemImport:
414 return LayerSupportBase::IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
415 case LayerType::Merge:
416 return LayerSupportBase::IsMergeSupported(infos[0],
417 infos[1],
418 infos[2],
419 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000420 case LayerType::Minimum:
421 return IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
422 case LayerType::Multiplication:
423 return IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
424 case LayerType::Normalization:
425 return IsNormalizationSupported(infos[0],
426 infos[1],
427 *(PolymorphicDowncast<const NormalizationDescriptor*>(&descriptor)),
428 reasonIfUnsupported);
429 case LayerType::Output:
430 return IsOutputSupported(infos[0], reasonIfUnsupported);
431 case LayerType::Pad:
432 return IsPadSupported(infos[0],
433 infos[1],
434 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
435 reasonIfUnsupported);
436 case LayerType::Permute:
437 return IsPermuteSupported(infos[0],
438 infos[1],
439 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
440 reasonIfUnsupported);
441 case LayerType::Pooling2d:
442 return IsPooling2dSupported(infos[0],
443 infos[1],
444 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
445 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100446 case LayerType::Pooling3d:
447 return IsPooling3dSupported(infos[0],
448 infos[1],
449 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
450 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000451 case LayerType::Prelu:
452 return IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000453 case LayerType::QLstm:
454 return IsQLstmSupported(infos[0],
455 infos[1],
456 infos[2],
457 infos[3],
458 infos[4],
459 infos[5],
460 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
461 lstmParamsInfo.value(),
462 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000463 case LayerType::Quantize:
464 return IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
465 case LayerType::QuantizedLstm:
466 return IsQuantizedLstmSupported(infos[0],
467 infos[1],
468 infos[2],
469 infos[3],
470 infos[4],
471 quantizedLstmParamsInfo.value(),
472 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000473 case LayerType::Rank:
474 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000475 case LayerType::Reshape:
476 return IsReshapeSupported(infos[0],
477 infos[1],
478 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
479 reasonIfUnsupported);
480 case LayerType::Resize:
481 return IsResizeSupported(infos[0],
482 infos[1],
483 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
484 reasonIfUnsupported);
485 case LayerType::Reduce:
486 return IsReduceSupported(infos[0],
487 infos[1],
488 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
489 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000490 case LayerType::Shape:
491 return LayerSupportBase::IsShapeSupported(infos[0],
492 infos[1],
493 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000494 case LayerType::Slice:
495 return IsSliceSupported(infos[0],
496 infos[1],
497 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
498 reasonIfUnsupported);
499 case LayerType::Softmax:
500 return IsSoftmaxSupported(infos[0],
501 infos[1],
502 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
503 reasonIfUnsupported);
504 case LayerType::SpaceToBatchNd:
505 return IsSpaceToBatchNdSupported(infos[0],
506 infos[1],
507 *(PolymorphicDowncast<const SpaceToBatchNdDescriptor*>(&descriptor)),
508 reasonIfUnsupported);
509 case LayerType::SpaceToDepth:
510 return IsSpaceToDepthSupported(infos[0],
511 infos[1],
512 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
513 reasonIfUnsupported);
514 case LayerType::Splitter:
515 {
516 std::vector<TensorInfo> outputInfos;
517 for (uint32_t i = 1; i < infos.size(); i++)
518 {
519 outputInfos.push_back(infos[i]);
520 }
521 return IsSplitterSupported(infos[0],
522 {outputInfos.begin(), outputInfos.end()},
523 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
524 reasonIfUnsupported);
525 }
526 case LayerType::Stack:
527 {
528 std::vector<const TensorInfo*> inputInfos;
529 for (uint32_t i = 0; i < infos.size() - 1; i++)
530 {
531 inputInfos.push_back(&infos[i]);
532 }
533 return IsStackSupported(inputInfos,
534 infos[infos.size() - 1],
535 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
536 reasonIfUnsupported);
537 }
538 case LayerType::StridedSlice:
539 return IsStridedSliceSupported(infos[0],
540 infos[1],
541 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
542 reasonIfUnsupported);
543 case LayerType::Subtraction:
544 return IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
545 case LayerType::Transpose:
546 return IsTransposeSupported(infos[0],
547 infos[1],
548 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
549 reasonIfUnsupported);
550 case LayerType::TransposeConvolution2d:
551 {
552 if (infos.size() != 4)
553 {
554 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
555 "TensorInfos should be of format: {input, output, weights, biases}.");
556 }
557
558 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
559 if (infos[3] == TensorInfo())
560 {
561 return IsTransposeConvolution2dSupported(infos[0],
562 infos[1],
563 desc,
564 infos[2],
565 EmptyOptional(),
566 reasonIfUnsupported);
567 }
568 else
569 {
570 return IsTransposeConvolution2dSupported(infos[0],
571 infos[1],
572 desc,
573 infos[2],
574 infos[3],
575 reasonIfUnsupported);
576 }
577 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000578 case LayerType::UnidirectionalSequenceLstm:
579 return IsUnidirectionalSequenceLstmSupported(infos[0],
580 infos[1],
581 infos[2],
582 infos[3],
583 infos[4],
584 infos[5],
585 *(PolymorphicDowncast<const
586 UnidirectionalSequenceLstmDescriptor*>(&descriptor)),
587 lstmParamsInfo.value(),
588 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000589 case LayerType::Unmap:
590 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000591 default:
592 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000593 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100594 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000595 return false;
596 }
597}
598
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100599bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
600 const TensorInfo& output,
601 const ActivationDescriptor& descriptor,
602 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000603{
Jan Eilers8eb25602020-03-09 12:13:48 +0000604 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100605 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
606 reasonIfUnsupported,
607 input,
608 output,
609 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000610}
611
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100612bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
613 const TensorInfo& input1,
614 const TensorInfo& output,
615 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000616{
telsoa01c577f2c2018-08-31 09:22:23 +0100617 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
618 reasonIfUnsupported,
619 input0,
620 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000621 output,
622 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000623}
624
James Conroyd47a0642019-09-17 14:22:06 +0100625bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
626 const TensorInfo& output,
627 const ArgMinMaxDescriptor& descriptor,
628 Optional<std::string&> reasonIfUnsupported) const
629{
630 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
631 reasonIfUnsupported,
632 input,
633 output,
634 descriptor);
635}
636
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100637bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
638 const TensorInfo& inputY,
639 const TensorInfo& output,
640 const BatchMatMulDescriptor& descriptor,
641 Optional<std::string&> reasonIfUnsupported) const
642{
643 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
644 reasonIfUnsupported,
645 inputX,
646 inputY,
647 output,
648 descriptor);
649}
650
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100651bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
652 const TensorInfo& output,
653 const TensorInfo& mean,
654 const TensorInfo& var,
655 const TensorInfo& beta,
656 const TensorInfo& gamma,
657 const BatchNormalizationDescriptor& descriptor,
658 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000659{
telsoa01c577f2c2018-08-31 09:22:23 +0100660 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
661 reasonIfUnsupported,
662 input,
663 output,
664 mean,
665 var,
666 beta,
667 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000668 descriptor,
669 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000670}
671
Mike Kelly56858022020-01-27 12:14:47 +0000672bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
673 const TensorInfo& output,
674 const BatchToSpaceNdDescriptor& descriptor,
675 Optional<std::string&> reasonIfUnsupported) const
676{
677 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
678 reasonIfUnsupported,
679 input,
680 output,
681 descriptor);
682}
683
Sadik Armagan48f011e2021-04-21 10:50:34 +0100684bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
685 const TensorInfo& output,
686 Optional<std::string&> reasonIfUnsupported) const
687{
688 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
689 reasonIfUnsupported,
690 input,
691 output);
692}
693
Teresa Charline89dd692021-09-01 16:30:34 +0100694bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
695 const TensorInfo& output,
696 const ChannelShuffleDescriptor& descriptor,
697 Optional<std::string&> reasonIfUnsupported) const
698{
699 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
700 reasonIfUnsupported,
701 input,
702 output,
703 descriptor);
704}
705
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100706bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
707 const TensorInfo& input1,
708 const TensorInfo& output,
709 const ComparisonDescriptor& descriptor,
710 Optional<std::string&> reasonIfUnsupported) const
711{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100712
Teresa Charlincedd34f2020-03-30 11:17:30 +0100713 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
714 reasonIfUnsupported,
715 input0,
716 input1,
717 output,
718 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100719}
720
Jim Flynn906f9462019-05-10 13:55:21 +0100721bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
722 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000723 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100724 Optional<std::string&> reasonIfUnsupported) const
725{
Jim Flynne242f2d2019-05-22 14:24:13 +0100726 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
727 {
728 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
729 return false;
730 }
731
732 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
733 if(concatInnerAxis < 3) // Width, height, or channels
734 {
735 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
736 reasonIfUnsupported,
737 inputs,
738 output,
739 descriptor);
740 }
741 else if (concatInnerAxis == 3)
742 {
743 for (auto& input : inputs)
744 {
745 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
746 {
747 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
748 return false;
749 }
750 }
751 return true; // Sub-tensors support concat along batch
752 }
753 else // > 4 dimensions not supported.
754 {
755 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
756 return false;
757 }
Jim Flynn906f9462019-05-10 13:55:21 +0100758}
759
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100760bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
761 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000762{
Mike Kelly0886ac42020-04-27 09:55:40 +0100763 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
764 reasonIfUnsupported,
765 output);
telsoa014fcda012018-03-09 14:13:49 +0000766}
767
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100768bool NeonLayerSupport::IsConvertBf16ToFp32Supported(const TensorInfo& input,
769 const TensorInfo& output,
770 Optional<std::string&> reasonIfUnsupported) const
771{
772 armnn::IgnoreUnused(input);
773 armnn::IgnoreUnused(output);
774 armnn::IgnoreUnused(reasonIfUnsupported);
775 return true;
776}
777
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100778bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
779 const TensorInfo& output,
780 Optional<std::string&> reasonIfUnsupported) const
781{
Jan Eilers8eb25602020-03-09 12:13:48 +0000782 armnn::IgnoreUnused(input);
783 armnn::IgnoreUnused(output);
784 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100785 return true;
786}
787
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100788bool NeonLayerSupport::IsConvertFp32ToBf16Supported(const TensorInfo& input,
789 const TensorInfo& output,
790 Optional<std::string&> reasonIfUnsupported) const
791{
792 armnn::IgnoreUnused(input);
793 armnn::IgnoreUnused(output);
794 armnn::IgnoreUnused(reasonIfUnsupported);
795 return true;
796}
797
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100798bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
799 const TensorInfo& output,
800 Optional<std::string&> reasonIfUnsupported) const
801{
Jan Eilers8eb25602020-03-09 12:13:48 +0000802 armnn::IgnoreUnused(input);
803 armnn::IgnoreUnused(output);
804 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100805 return true;
806}
807
808bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
809 const TensorInfo& output,
810 const Convolution2dDescriptor& descriptor,
811 const TensorInfo& weights,
812 const Optional<TensorInfo>& biases,
813 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000814{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100815 bool isFastMathEnabled = false;
816#if defined(ARMCOMPUTENEON_ENABLED)
817 if (m_ModelContextPtr)
818 {
819 if (m_ModelContextPtr.get() != nullptr)
820 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100821 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100822 if (modelOptions)
823 {
824 isFastMathEnabled = modelOptions->IsFastMathEnabled();
825 }
826 }
827 }
828#endif
829
surmeh013537c2c2018-05-18 16:31:43 +0100830 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
831 reasonIfUnsupported,
832 input,
833 output,
834 descriptor,
835 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100836 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000837 isFastMathEnabled,
838 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000839}
840
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100841bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
842 const TensorInfo& output,
843 const Convolution3dDescriptor& descriptor,
844 const TensorInfo& weights,
845 const Optional<TensorInfo>& biases,
846 Optional<std::string&> reasonIfUnsupported) const
847{
848 bool isFastMathEnabled = false;
849#if defined(ARMCOMPUTENEON_ENABLED)
850 if (m_ModelContextPtr)
851 {
852 if (m_ModelContextPtr.get() != nullptr)
853 {
854 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
855 if (modelOptions)
856 {
857 isFastMathEnabled = modelOptions->IsFastMathEnabled();
858 }
859 }
860 }
861#endif
862
863 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
864 reasonIfUnsupported,
865 input,
866 output,
867 descriptor,
868 weights,
869 biases,
870 isFastMathEnabled,
871 nullptr);
872}
873
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100874bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
875 const TensorInfo& output,
876 const DepthToSpaceDescriptor& descriptor,
877 Optional<std::string&> reasonIfUnsupported) const
878{
879 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
880 reasonIfUnsupported,
881 input,
882 output,
883 descriptor);
884}
885
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100886bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
887 const TensorInfo& output,
888 const DepthwiseConvolution2dDescriptor& descriptor,
889 const TensorInfo& weights,
890 const Optional<TensorInfo>& biases,
891 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000892{
telsoa01c577f2c2018-08-31 09:22:23 +0100893 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
894 reasonIfUnsupported,
895 input,
896 output,
897 descriptor,
898 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +0000899 biases,
900 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000901}
902
Narumol Prangnawarat01961a72019-05-30 16:47:12 +0100903bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
904 const TensorInfo& output,
905 Optional<std::string&> reasonIfUnsupported) const
906{
907 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
908 reasonIfUnsupported,
909 input,
910 output);
911}
912
Pablo Tellof0bd6832019-04-26 17:58:13 +0100913bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
914 const TensorInfo& output,
915 const DepthwiseConvolution2dDescriptor& descriptor,
916 const TensorInfo& weights,
917 const Optional<TensorInfo>& biases,
918 Optional<std::string&> reasonIfUnsupported) const
919{
920 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
921 reasonIfUnsupported,
922 input,
923 output,
924 descriptor,
925 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +0000926 biases,
927 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +0100928}
929
josh minor4a3c6102020-01-06 16:40:46 -0600930bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
931 const TensorInfo& output,
932 const ElementwiseUnaryDescriptor& descriptor,
933 Optional<std::string&> reasonIfUnsupported) const
934{
Derek Lambertic77874a2020-04-28 13:34:56 +0100935 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -0600936 {
Derek Lambertic77874a2020-04-28 13:34:56 +0100937 case UnaryOperation::Abs:
938 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
939 reasonIfUnsupported,
940 input,
941 output);
942 case UnaryOperation::Exp:
943 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
944 reasonIfUnsupported,
945 input,
946 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100947 case UnaryOperation::LogicalNot:
948 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
949 reasonIfUnsupported,
950 input,
951 output);
952 case UnaryOperation::Log:
953 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
954 reasonIfUnsupported,
955 input,
956 output);
Derek Lambertic77874a2020-04-28 13:34:56 +0100957 case UnaryOperation::Neg:
958 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
959 reasonIfUnsupported,
960 input,
961 output);
962 case UnaryOperation::Rsqrt:
963 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
964 reasonIfUnsupported,
965 input,
966 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +0000967 case UnaryOperation::Sin:
968 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
969 reasonIfUnsupported,
970 input,
971 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +0100972 case UnaryOperation::Sqrt:
973 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
974 reasonIfUnsupported,
975 input,
976 output);
Derek Lambertic77874a2020-04-28 13:34:56 +0100977 default:
978 return false;
josh minor4a3c6102020-01-06 16:40:46 -0600979 }
josh minor4a3c6102020-01-06 16:40:46 -0600980}
981
Teresa Charlin4b10fef2020-07-29 09:36:41 +0100982bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
983 const TensorInfo& output,
984 const FillDescriptor& descriptor,
985 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +0100986{
Teresa Charlin4b10fef2020-07-29 09:36:41 +0100987 armnn::IgnoreUnused(input);
988 armnn::IgnoreUnused(output);
989 armnn::IgnoreUnused(descriptor);
990
991 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +0100992}
993
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100994bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
995 const TensorInfo& output,
996 Optional<std::string&> reasonIfUnsupported) const
997{
Jan Eilers8eb25602020-03-09 12:13:48 +0000998 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100999 return IsNeonBackendSupported(reasonIfUnsupported) &&
1000 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1001 input.GetDataType(),
1002 &FalseFuncF16<>,
1003 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001004 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001005 &FalseFuncI32<>,
1006 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001007}
1008
1009bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1010 const TensorInfo& output,
1011 const TensorInfo& weights,
1012 const TensorInfo& biases,
1013 const FullyConnectedDescriptor& descriptor,
1014 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001015{
telsoa01c577f2c2018-08-31 09:22:23 +01001016 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1017 reasonIfUnsupported,
1018 input,
1019 output,
1020 weights,
1021 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001022 descriptor,
1023 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001024}
1025
Teresa Charlinf540eb82020-04-10 19:24:55 +01001026bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1027 const TensorInfo& input1,
1028 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001029 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001030 Optional<std::string&> reasonIfUnsupported) const
1031{
1032 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1033 reasonIfUnsupported,
1034 input0,
1035 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001036 output,
1037 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001038}
1039
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001040bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1041 const TensorInfo& input1,
1042 const TensorInfo& output,
1043 Optional<std::string&> reasonIfUnsupported) const
1044{
1045 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1046 reasonIfUnsupported,
1047 input0,
1048 input1,
1049 output);
1050}
1051
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001052bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1053 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001054{
Derek Lamberti901ea112019-12-10 22:07:09 +00001055 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001056}
1057
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001058bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1059 const TensorInfo& output,
1060 const InstanceNormalizationDescriptor& descriptor,
1061 Optional<std::string&> reasonIfUnsupported) const
1062{
1063 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1064 reasonIfUnsupported,
1065 input,
1066 output,
1067 descriptor);
1068}
1069
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001070bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1071 const TensorInfo& output,
1072 const L2NormalizationDescriptor& descriptor,
1073 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001074{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001075 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001076}
1077
James Conroy177df1e2020-11-13 10:18:51 +00001078bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1079 const TensorInfo& input1,
1080 const TensorInfo& output,
1081 const LogicalBinaryDescriptor& descriptor,
1082 Optional<std::string&> reasonIfUnsupported) const
1083{
1084 switch(descriptor.m_Operation)
1085 {
1086 case LogicalBinaryOperation::LogicalAnd:
1087 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1088 reasonIfUnsupported,
1089 input0,
1090 input1,
1091 output);
1092 case LogicalBinaryOperation::LogicalOr:
1093 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1094 reasonIfUnsupported,
1095 input0,
1096 input1,
1097 output);
1098 default:
1099 return false;
1100 }
1101}
1102
Keith Davis69e653f2020-07-02 11:49:26 +01001103bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1104 const TensorInfo& output,
1105 const LogSoftmaxDescriptor& descriptor,
1106 Optional<std::string&> reasonIfUnsupported) const
1107{
1108 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1109}
1110
Jan Eilersad5293a2019-07-08 09:57:55 +01001111bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1112 const TensorInfo& outputStateIn,
1113 const TensorInfo& cellStateIn,
1114 const TensorInfo& scratchBuffer,
1115 const TensorInfo& outputStateOut,
1116 const TensorInfo& cellStateOut,
1117 const TensorInfo& output,
1118 const LstmDescriptor& descriptor,
1119 const LstmInputParamsInfo& paramsInfo,
1120 Optional<std::string&> reasonIfUnsupported) const
1121{
1122 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1123 reasonIfUnsupported,
1124 input,
1125 outputStateIn,
1126 cellStateIn,
1127 scratchBuffer,
1128 outputStateOut,
1129 cellStateOut,
1130 output,
1131 descriptor,
1132 paramsInfo);
1133}
1134
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001135bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1136 const TensorInfo& input1,
1137 const TensorInfo& output,
1138 Optional<std::string&> reasonIfUnsupported) const
1139{
1140 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1141 reasonIfUnsupported,
1142 input0,
1143 input1,
1144 output);
1145}
1146
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001147bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1148 const TensorInfo& output,
1149 const MeanDescriptor& descriptor,
1150 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001151{
Matthew Benthamfd899962018-12-31 15:49:42 +00001152 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1153 reasonIfUnsupported,
1154 input,
1155 output,
1156 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001157}
1158
Conor Kennedy54b21692019-01-09 07:57:38 +00001159bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1160 const TensorInfo& input1,
1161 const TensorInfo& output,
1162 Optional<std::string&> reasonIfUnsupported) const
1163{
1164 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1165 reasonIfUnsupported,
1166 input0,
1167 input1,
1168 output);
1169}
1170
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001171bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1172 const TensorInfo& input1,
1173 const TensorInfo& output,
1174 Optional<std::string&> reasonIfUnsupported) const
1175{
1176 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1177 reasonIfUnsupported,
1178 input0,
1179 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001180 output,
1181 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001182}
1183
Pablo Telloe61f0712020-01-23 10:37:17 +00001184bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1185 const TensorInfo& input1,
1186 const TensorInfo& output,
1187 Optional<std::string&> reasonIfUnsupported) const
1188{
1189 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1190 reasonIfUnsupported,
1191 input0,
1192 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001193 output,
1194 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001195}
1196
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001197bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1198 const TensorInfo& output,
1199 const NormalizationDescriptor& descriptor,
1200 Optional<std::string&> reasonIfUnsupported) const
1201{
1202 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1203 reasonIfUnsupported,
1204 input,
1205 output,
1206 descriptor);
1207}
1208
1209bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1210 Optional<std::string&> reasonIfUnsupported) const
1211{
Derek Lamberti901ea112019-12-10 22:07:09 +00001212 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001213}
1214
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001215bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1216 const TensorInfo& output,
1217 const PadDescriptor& descriptor,
1218 Optional<std::string&> reasonIfUnsupported) const
1219{
1220 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1221 reasonIfUnsupported,
1222 input,
1223 output,
1224 descriptor);
1225}
1226
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001227bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1228 const TensorInfo& output,
1229 const PermuteDescriptor& descriptor,
1230 Optional<std::string&> reasonIfUnsupported) const
1231{
1232 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001233}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001234
1235bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1236 const TensorInfo& output,
1237 const Pooling2dDescriptor& descriptor,
1238 Optional<std::string&> reasonIfUnsupported) const
1239{
1240 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1241}
1242
Ryan OShea19e79422022-05-04 00:38:03 +01001243bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1244 const TensorInfo& output,
1245 const Pooling3dDescriptor& descriptor,
1246 Optional<std::string&> reasonIfUnsupported) const
1247{
1248 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1249}
1250
Nikhil Raj9b461482019-07-03 15:58:31 +01001251bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1252 const armnn::TensorInfo &alpha,
1253 const armnn::TensorInfo &output,
1254 armnn::Optional<std::string &> reasonIfUnsupported) const
1255{
1256 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1257}
1258
James Conroycc340932020-05-12 18:08:52 +01001259bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1260 const TensorInfo& previousOutputIn,
1261 const TensorInfo& previousCellStateIn,
1262 const TensorInfo& outputStateOut,
1263 const TensorInfo& cellStateOut,
1264 const TensorInfo& output,
1265 const QLstmDescriptor& descriptor,
1266 const LstmInputParamsInfo& paramsInfo,
1267 Optional<std::string&> reasonIfUnsupported) const
1268{
1269 // Check required here in order to pass IsLayerSupported for datatypes tests
1270 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1271 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1272 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1273 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1274 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1275 output.GetDataType() == armnn::DataType::QAsymmS8)
1276 {
1277 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1278 reasonIfUnsupported,
1279 input,
1280 previousCellStateIn,
1281 previousOutputIn,
1282 cellStateOut,
1283 outputStateOut,
1284 output,
1285 descriptor,
1286 paramsInfo);
1287 }
1288 else
1289 {
1290 return false;
1291 }
1292}
1293
Sadik Armaganfabc2892019-05-31 09:05:11 +01001294bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1295 const TensorInfo& output,
1296 Optional<std::string&> reasonIfUnsupported) const
1297{
1298 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1299 reasonIfUnsupported,
1300 input,
1301 output);
1302}
1303
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001304bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1305 const TensorInfo& cellStateIn,
1306 const TensorInfo& outputStateIn,
1307 const TensorInfo& cellStateOut,
1308 const TensorInfo& outputStateOut,
1309 const QuantizedLstmInputParamsInfo& paramsInfo,
1310 Optional<std::string&> reasonIfUnsupported) const
1311{
1312 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1313 reasonIfUnsupported,
1314 input,
1315 cellStateIn,
1316 outputStateIn,
1317 cellStateOut,
1318 outputStateOut,
1319 paramsInfo);
1320}
1321
Sadik Armagana2747482021-02-09 10:28:54 +00001322bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1323 const TensorInfo& output,
1324 const ReduceDescriptor& descriptor,
1325 Optional<std::string&> reasonIfUnsupported) const
1326{
1327 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1328 reasonIfUnsupported,
1329 input,
1330 output,
1331 descriptor);
1332}
1333
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001334bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001335 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001336 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001337 Optional<std::string&> reasonIfUnsupported) const
1338{
Jan Eilers8eb25602020-03-09 12:13:48 +00001339 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001340 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1341 reasonIfUnsupported,
1342 input,
1343 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001344}
1345
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001346bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1347 const TensorInfo& output,
1348 const ResizeDescriptor& descriptor,
1349 Optional<std::string&> reasonIfUnsupported) const
1350{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001351 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1352 reasonIfUnsupported,
1353 input,
1354 output,
1355 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001356}
1357
josh minor036f02d2019-11-15 14:53:22 -06001358bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1359 const TensorInfo& output,
1360 const SliceDescriptor& descriptor,
1361 Optional<std::string&> reasonIfUnsupported) const
1362{
1363 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1364 reasonIfUnsupported,
1365 input,
1366 output,
1367 descriptor);
1368}
1369
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001370bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1371 const TensorInfo& output,
1372 const SoftmaxDescriptor& descriptor,
1373 Optional<std::string&> reasonIfUnsupported) const
1374{
1375 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1376}
1377
Mike Kelly0be3a882020-01-24 11:27:50 +00001378bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1379 const TensorInfo& output,
1380 const SpaceToBatchNdDescriptor& descriptor,
1381 Optional<std::string&> reasonIfUnsupported) const
1382{
1383 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1384 reasonIfUnsupported,
1385 input,
1386 output,
1387 descriptor);
1388}
1389
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001390bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001391 const TensorInfo& output,
1392 const SpaceToDepthDescriptor& descriptor,
1393 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001394{
1395 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1396 reasonIfUnsupported,
1397 input,
1398 output,
1399 descriptor);
1400}
1401
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001402bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001403 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1404 const ViewsDescriptor& descriptor,
1405 Optional<std::string&> reasonIfUnsupported) const
1406{
1407#if defined(ARMCOMPUTENEON_ENABLED)
1408 // Split along the last dimension, cannot use sub-tensors
1409 // as width and height of the sub-tensors do not match
1410 // the width and height of the parent tensor
1411 // in case of input with more than 2D.
1412 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1413 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1414 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1415 {
1416 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1417 reasonIfUnsupported,
1418 input,
1419 outputs,
1420 *splitAxis.begin());
1421 }
1422#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001423 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001424 for (auto output : outputs)
1425 {
1426 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1427 {
1428 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1429 return false;
1430 }
1431 }
1432 return true;
1433}
1434
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001435bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1436 const TensorInfo& output,
1437 const StackDescriptor& descriptor,
1438 Optional<std::string&> reasonIfUnsupported) const
1439{
1440 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1441 reasonIfUnsupported,
1442 inputs,
1443 output,
1444 descriptor);
1445}
1446
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001447bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1448 const TensorInfo& output,
1449 const StridedSliceDescriptor& descriptor,
1450 Optional<std::string&> reasonIfUnsupported) const
1451{
1452 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1453 reasonIfUnsupported,
1454 input,
1455 output,
1456 descriptor);
1457}
1458
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001459bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1460 const TensorInfo& input1,
1461 const TensorInfo& output,
1462 Optional<std::string&> reasonIfUnsupported) const
1463{
1464 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1465 reasonIfUnsupported,
1466 input0,
1467 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001468 output,
1469 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001470}
1471
Sadik Armagan581742d2019-08-12 14:11:37 +01001472bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1473 const TensorInfo& output,
1474 const TransposeConvolution2dDescriptor& descriptor,
1475 const TensorInfo& weights,
1476 const Optional<TensorInfo>& biases,
1477 Optional<std::string&> reasonIfUnsupported) const
1478{
1479 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1480 reasonIfUnsupported,
1481 input,
1482 output,
1483 descriptor,
1484 weights,
1485 biases);
1486}
1487
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001488bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1489 const TensorInfo& output,
1490 const TransposeDescriptor& descriptor,
1491 Optional<std::string&> reasonIfUnsupported) const
1492{
1493 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1494}
1495
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001496bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1497 const TensorInfo& outputStateIn,
1498 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001499 const TensorInfo& outputStateOut,
1500 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001501 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001502 const UnidirectionalSequenceLstmDescriptor& descriptor,
1503 const LstmInputParamsInfo& paramsInfo,
1504 Optional<std::string&> reasonIfUnsupported) const
1505{
Mike Kelly12994962022-04-21 11:57:09 +01001506 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1507 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1508 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1509 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1510 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1511 output.GetDataType() == armnn::DataType::QAsymmS8)
1512 {
1513 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1514 reasonIfUnsupported,
1515 input,
1516 outputStateIn,
1517 cellStateIn,
1518 outputStateOut,
1519 cellStateOut,
1520 output,
1521 descriptor,
1522 paramsInfo);
1523 }
1524 else
1525 {
1526 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1527 reasonIfUnsupported,
1528 input,
1529 outputStateIn,
1530 cellStateIn,
1531 outputStateOut,
1532 cellStateOut,
1533 output,
1534 descriptor,
1535 paramsInfo);
1536 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001537}
1538
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001539} // namespace armnn