blob: 26b650b49d788dcec3124a89960ceb206b9f6383 [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"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000027#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000028#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010029#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010030#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010031#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010032#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010033#include "workloads/NeonConstantWorkload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010034#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010035#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010036#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010037#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010038#include "workloads/NeonDequantizeWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010039#include "workloads/NeonExpWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010040#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010041#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010042#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010043#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000044#include "workloads/NeonLogicalAndWorkload.hpp"
45#include "workloads/NeonLogicalNotWorkload.hpp"
46#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010047#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000048#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000049#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000050#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000051#include "workloads/NeonMultiplicationWorkload.hpp"
Pablo Telloe61f0712020-01-23 10:37:17 +000052#include "workloads/NeonDivisionWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000053#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010054#include "workloads/NeonNormalizationFloatWorkload.hpp"
55#include "workloads/NeonFullyConnectedWorkload.hpp"
Teresa Charlinf540eb82020-04-10 19:24:55 +010056#include "workloads/NeonGatherWorkload.hpp"
Teresa Charlinbd22c7d2022-04-26 18:14:12 +010057#include "workloads/NeonGatherNdWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000058#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010059#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010060#include "workloads/NeonPooling2dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010061#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010062#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010063#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010064#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000065#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000066#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010067#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010068#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010069#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060070#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010071#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000072#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010073#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010074#include "workloads/NeonSplitterWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010075#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010076#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000077#include "workloads/NeonSubtractionWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010078#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000079#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000080#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010081#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000082#endif
83
telsoa014fcda012018-03-09 14:13:49 +000084namespace armnn
85{
telsoa014fcda012018-03-09 14:13:49 +000086
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010087namespace
arovir017ff76c52018-10-09 09:40:58 +010088{
telsoa014fcda012018-03-09 14:13:49 +000089
Derek Lamberti901ea112019-12-10 22:07:09 +000090template< typename ... Args>
91bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +000092{
Jan Eilers8eb25602020-03-09 12:13:48 +000093 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +000094#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000095 return true;
96#else
Derek Lamberti0790dce2019-04-15 18:37:35 +010097 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +000098 return false;
99#endif
100}
101
telsoa01c577f2c2018-08-31 09:22:23 +0100102template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100103bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000104 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100105 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000106 Uint8Func uint8FuncPtr,
107 Params&&... params)
108{
109 return IsNeonBackendSupported(reasonIfUnsupported) &&
110 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
111 dataType,
112 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +0100113 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000114 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +0000115 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000116 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +0000117 std::forward<Params>(params)...);
118}
119
Matteo Martincighd95e9062019-01-31 15:35:59 +0000120#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000121template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100122inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000123{
124 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
125 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
126 if (!supported && reasonIfUnsupported)
127 {
arovir01085f0a42018-10-08 14:48:19 +0100128 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000129 }
130 return supported;
131}
132
133#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
134 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
135#else
136#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000137 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000138#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100139} // anonymous namespace
140
Sadik Armagan045f6be2020-09-10 13:37:32 +0100141NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
142 : m_ModelContextPtr(modelContextPtr)
143{
144}
145
146NeonLayerSupport::NeonLayerSupport()
147 : m_ModelContextPtr(nullptr)
148{
149}
150
Cathal Corbett34b429c2021-12-24 12:24:40 +0000151bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
152 const std::vector<TensorInfo>& infos,
153 const BaseDescriptor& descriptor,
154 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
155 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
156 Optional<std::string&> reasonIfUnsupported) const
157{
158 switch (type)
159 {
160 case LayerType::Activation:
161 return IsActivationSupported(infos[0],
162 infos[1],
163 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
164 reasonIfUnsupported);
165 case LayerType::Addition:
166 return IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
167 case LayerType::ArgMinMax:
168 return IsArgMinMaxSupported(infos[0],
169 infos[1],
170 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
171 reasonIfUnsupported);
172 case LayerType::BatchNormalization:
173 return IsBatchNormalizationSupported(infos[0],
174 infos[1],
175 infos[2],
176 infos[3],
177 infos[4],
178 infos[5],
179 *(PolymorphicDowncast<const BatchNormalizationDescriptor*>
180 (&descriptor)),
181 reasonIfUnsupported);
182 case LayerType::BatchToSpaceNd:
183 return IsBatchToSpaceNdSupported(infos[0],
184 infos[1],
185 *(PolymorphicDowncast<const BatchToSpaceNdDescriptor*>(&descriptor)),
186 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000187 case LayerType::Cast:
188 return IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
189 case LayerType::ChannelShuffle:
190 return IsChannelShuffleSupported(infos[0],
191 infos[1],
192 *(PolymorphicDowncast<const ChannelShuffleDescriptor*>(&descriptor)),
193 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000194 case LayerType::Comparison:
195 return IsComparisonSupported(infos[0],
196 infos[1],
197 infos[2],
198 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
199 reasonIfUnsupported);
200 case LayerType::Concat:
201 {
202 std::vector<const TensorInfo*> inputInfos;
203 for (uint32_t i = 0; i < (infos.size() - 1); i++)
204 {
205 inputInfos.push_back(&infos[i]);
206 }
207 return IsConcatSupported(inputInfos,
208 infos[infos.size() - 1],
209 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
210 reasonIfUnsupported);
211 }
212 case LayerType::Constant:
213 return IsConstantSupported(infos[0], reasonIfUnsupported);
214 case LayerType::ConvertBf16ToFp32:
215 return IsConvertBf16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
216 case LayerType::ConvertFp16ToFp32:
217 return IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
218 case LayerType::ConvertFp32ToBf16:
219 return IsConvertFp32ToBf16Supported(infos[0], infos[1], reasonIfUnsupported);
220 case LayerType::ConvertFp32ToFp16:
221 return IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
222 case LayerType::Convolution2d:
223 {
224 if (infos.size() != 4)
225 {
226 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
227 "TensorInfos should be of format: {input, output, weights, biases}.");
228 }
229
230 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
231 if (infos[3] == TensorInfo())
232 {
233 return IsConvolution2dSupported(infos[0],
234 infos[1],
235 desc,
236 infos[2],
237 EmptyOptional(),
238 reasonIfUnsupported);
239 }
240 else
241 {
242 return IsConvolution2dSupported(infos[0],
243 infos[1],
244 desc,
245 infos[2],
246 infos[3],
247 reasonIfUnsupported);
248 }
249 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000250 case LayerType::Convolution3d:
251 {
252 if (infos.size() != 4)
253 {
254 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
255 "TensorInfos should be of format: {input, output, weights, biases}.");
256 }
257
258 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
259 if (infos[3] == TensorInfo())
260 {
261 return IsConvolution3dSupported(infos[0],
262 infos[1],
263 desc,
264 infos[2],
265 EmptyOptional(),
266 reasonIfUnsupported);
267 }
268 else
269 {
270 return IsConvolution3dSupported(infos[0],
271 infos[1],
272 desc,
273 infos[2],
274 infos[3],
275 reasonIfUnsupported);
276 }
277 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000278 case LayerType::DepthToSpace:
279 return IsDepthToSpaceSupported(infos[0],
280 infos[1],
281 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
282 reasonIfUnsupported);
283 case LayerType::DepthwiseConvolution2d:
284 {
285 if (infos.size() != 4)
286 {
287 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
288 "TensorInfos should be of format: {input, output, weights, biases}.");
289 }
290
291 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
292 if (infos[3] == TensorInfo())
293 {
294 return IsDepthwiseConvolutionSupported(infos[0],
295 infos[1],
296 desc,
297 infos[2],
298 EmptyOptional(),
299 reasonIfUnsupported);
300 }
301 else
302 {
303 return IsDepthwiseConvolutionSupported(infos[0],
304 infos[1],
305 desc,
306 infos[2],
307 infos[3],
308 reasonIfUnsupported);
309 }
310 }
311 case LayerType::Dequantize:
312 return IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000313 case LayerType::DetectionPostProcess:
314 {
315 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
316 return LayerSupportBase::IsDetectionPostProcessSupported(infos[0],
317 infos[1],
318 infos[2],
319 infos[3],
320 infos[4],
321 infos[5],
322 infos[6],
323 desc,
324 reasonIfUnsupported);
325 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000326 case LayerType::Division:
327 return IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
328 case LayerType::ElementwiseUnary:
329 return IsElementwiseUnarySupported(infos[0],
330 infos[1],
331 *(PolymorphicDowncast<const ElementwiseUnaryDescriptor*>(&descriptor)),
332 reasonIfUnsupported);
333 case LayerType::Fill:
334 return IsFillSupported(infos[0],
335 infos[1],
336 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
337 reasonIfUnsupported);
338 case LayerType::Floor:
339 return IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
340 case LayerType::FullyConnected:
341 return IsFullyConnectedSupported(infos[0],
342 infos[1],
343 infos[2],
344 infos[3],
345 *(PolymorphicDowncast<const FullyConnectedDescriptor*>(&descriptor)),
346 reasonIfUnsupported);
347 case LayerType::Gather:
348 return IsGatherSupported(infos[0],
349 infos[1],
350 infos[2],
351 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
352 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100353 case LayerType::GatherNd:
354 return IsGatherNdSupported(infos[0],
355 infos[1],
356 infos[2],
357 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000358 case LayerType::Input:
359 return IsInputSupported(infos[0], reasonIfUnsupported);
360 case LayerType::InstanceNormalization:
361 return IsInstanceNormalizationSupported(infos[0],
362 infos[1],
363 *(PolymorphicDowncast<const InstanceNormalizationDescriptor*>
364 (&descriptor)),
365 reasonIfUnsupported);
366 case LayerType::L2Normalization:
367 return IsL2NormalizationSupported(infos[0],
368 infos[1],
369 *(PolymorphicDowncast<const L2NormalizationDescriptor*>(&descriptor)),
370 reasonIfUnsupported);
371 case LayerType::LogicalBinary:
372 return IsLogicalBinarySupported(infos[0],
373 infos[1],
374 infos[2],
375 *(PolymorphicDowncast<const LogicalBinaryDescriptor*>(&descriptor)),
376 reasonIfUnsupported);
377 case LayerType::LogSoftmax:
378 return IsLogSoftmaxSupported(infos[0],
379 infos[1],
380 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
381 reasonIfUnsupported);
382 case LayerType::Lstm:
383 return IsLstmSupported(infos[0],
384 infos[1],
385 infos[2],
386 infos[3],
387 infos[4],
388 infos[5],
389 infos[6],
390 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
391 lstmParamsInfo.value(),
392 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000393 case LayerType::Map:
394 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000395 case LayerType::Maximum:
396 return IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
397 case LayerType::Mean:
398 return IsMeanSupported(infos[0],
399 infos[1],
400 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
401 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000402 case LayerType::MemCopy:
403 return LayerSupportBase::IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
404 case LayerType::MemImport:
405 return LayerSupportBase::IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
406 case LayerType::Merge:
407 return LayerSupportBase::IsMergeSupported(infos[0],
408 infos[1],
409 infos[2],
410 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000411 case LayerType::Minimum:
412 return IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
413 case LayerType::Multiplication:
414 return IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
415 case LayerType::Normalization:
416 return IsNormalizationSupported(infos[0],
417 infos[1],
418 *(PolymorphicDowncast<const NormalizationDescriptor*>(&descriptor)),
419 reasonIfUnsupported);
420 case LayerType::Output:
421 return IsOutputSupported(infos[0], reasonIfUnsupported);
422 case LayerType::Pad:
423 return IsPadSupported(infos[0],
424 infos[1],
425 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
426 reasonIfUnsupported);
427 case LayerType::Permute:
428 return IsPermuteSupported(infos[0],
429 infos[1],
430 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
431 reasonIfUnsupported);
432 case LayerType::Pooling2d:
433 return IsPooling2dSupported(infos[0],
434 infos[1],
435 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
436 reasonIfUnsupported);
437 case LayerType::Prelu:
438 return IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000439 case LayerType::QLstm:
440 return IsQLstmSupported(infos[0],
441 infos[1],
442 infos[2],
443 infos[3],
444 infos[4],
445 infos[5],
446 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
447 lstmParamsInfo.value(),
448 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000449 case LayerType::Quantize:
450 return IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
451 case LayerType::QuantizedLstm:
452 return IsQuantizedLstmSupported(infos[0],
453 infos[1],
454 infos[2],
455 infos[3],
456 infos[4],
457 quantizedLstmParamsInfo.value(),
458 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000459 case LayerType::Rank:
460 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000461 case LayerType::Reshape:
462 return IsReshapeSupported(infos[0],
463 infos[1],
464 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
465 reasonIfUnsupported);
466 case LayerType::Resize:
467 return IsResizeSupported(infos[0],
468 infos[1],
469 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
470 reasonIfUnsupported);
471 case LayerType::Reduce:
472 return IsReduceSupported(infos[0],
473 infos[1],
474 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
475 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000476 case LayerType::Shape:
477 return LayerSupportBase::IsShapeSupported(infos[0],
478 infos[1],
479 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000480 case LayerType::Slice:
481 return IsSliceSupported(infos[0],
482 infos[1],
483 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
484 reasonIfUnsupported);
485 case LayerType::Softmax:
486 return IsSoftmaxSupported(infos[0],
487 infos[1],
488 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
489 reasonIfUnsupported);
490 case LayerType::SpaceToBatchNd:
491 return IsSpaceToBatchNdSupported(infos[0],
492 infos[1],
493 *(PolymorphicDowncast<const SpaceToBatchNdDescriptor*>(&descriptor)),
494 reasonIfUnsupported);
495 case LayerType::SpaceToDepth:
496 return IsSpaceToDepthSupported(infos[0],
497 infos[1],
498 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
499 reasonIfUnsupported);
500 case LayerType::Splitter:
501 {
502 std::vector<TensorInfo> outputInfos;
503 for (uint32_t i = 1; i < infos.size(); i++)
504 {
505 outputInfos.push_back(infos[i]);
506 }
507 return IsSplitterSupported(infos[0],
508 {outputInfos.begin(), outputInfos.end()},
509 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
510 reasonIfUnsupported);
511 }
512 case LayerType::Stack:
513 {
514 std::vector<const TensorInfo*> inputInfos;
515 for (uint32_t i = 0; i < infos.size() - 1; i++)
516 {
517 inputInfos.push_back(&infos[i]);
518 }
519 return IsStackSupported(inputInfos,
520 infos[infos.size() - 1],
521 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
522 reasonIfUnsupported);
523 }
524 case LayerType::StridedSlice:
525 return IsStridedSliceSupported(infos[0],
526 infos[1],
527 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
528 reasonIfUnsupported);
529 case LayerType::Subtraction:
530 return IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
531 case LayerType::Transpose:
532 return IsTransposeSupported(infos[0],
533 infos[1],
534 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
535 reasonIfUnsupported);
536 case LayerType::TransposeConvolution2d:
537 {
538 if (infos.size() != 4)
539 {
540 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
541 "TensorInfos should be of format: {input, output, weights, biases}.");
542 }
543
544 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
545 if (infos[3] == TensorInfo())
546 {
547 return IsTransposeConvolution2dSupported(infos[0],
548 infos[1],
549 desc,
550 infos[2],
551 EmptyOptional(),
552 reasonIfUnsupported);
553 }
554 else
555 {
556 return IsTransposeConvolution2dSupported(infos[0],
557 infos[1],
558 desc,
559 infos[2],
560 infos[3],
561 reasonIfUnsupported);
562 }
563 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000564 case LayerType::UnidirectionalSequenceLstm:
565 return IsUnidirectionalSequenceLstmSupported(infos[0],
566 infos[1],
567 infos[2],
568 infos[3],
569 infos[4],
570 infos[5],
571 *(PolymorphicDowncast<const
572 UnidirectionalSequenceLstmDescriptor*>(&descriptor)),
573 lstmParamsInfo.value(),
574 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000575 case LayerType::Unmap:
576 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000577 default:
578 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000579 // debug, fakequantization, precompiled,
580 // standin, switch, pooling3d
Cathal Corbett34b429c2021-12-24 12:24:40 +0000581 return false;
582 }
583}
584
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100585bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
586 const TensorInfo& output,
587 const ActivationDescriptor& descriptor,
588 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000589{
Jan Eilers8eb25602020-03-09 12:13:48 +0000590 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100591 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
592 reasonIfUnsupported,
593 input,
594 output,
595 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000596}
597
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100598bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
599 const TensorInfo& input1,
600 const TensorInfo& output,
601 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000602{
telsoa01c577f2c2018-08-31 09:22:23 +0100603 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
604 reasonIfUnsupported,
605 input0,
606 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000607 output,
608 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000609}
610
James Conroyd47a0642019-09-17 14:22:06 +0100611bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
612 const TensorInfo& output,
613 const ArgMinMaxDescriptor& descriptor,
614 Optional<std::string&> reasonIfUnsupported) const
615{
616 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
617 reasonIfUnsupported,
618 input,
619 output,
620 descriptor);
621}
622
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100623bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
624 const TensorInfo& output,
625 const TensorInfo& mean,
626 const TensorInfo& var,
627 const TensorInfo& beta,
628 const TensorInfo& gamma,
629 const BatchNormalizationDescriptor& descriptor,
630 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000631{
telsoa01c577f2c2018-08-31 09:22:23 +0100632 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
633 reasonIfUnsupported,
634 input,
635 output,
636 mean,
637 var,
638 beta,
639 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000640 descriptor,
641 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000642}
643
Mike Kelly56858022020-01-27 12:14:47 +0000644bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
645 const TensorInfo& output,
646 const BatchToSpaceNdDescriptor& descriptor,
647 Optional<std::string&> reasonIfUnsupported) const
648{
649 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
650 reasonIfUnsupported,
651 input,
652 output,
653 descriptor);
654}
655
Sadik Armagan48f011e2021-04-21 10:50:34 +0100656bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
657 const TensorInfo& output,
658 Optional<std::string&> reasonIfUnsupported) const
659{
660 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
661 reasonIfUnsupported,
662 input,
663 output);
664}
665
Teresa Charline89dd692021-09-01 16:30:34 +0100666bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
667 const TensorInfo& output,
668 const ChannelShuffleDescriptor& descriptor,
669 Optional<std::string&> reasonIfUnsupported) const
670{
671 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
672 reasonIfUnsupported,
673 input,
674 output,
675 descriptor);
676}
677
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100678bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
679 const TensorInfo& input1,
680 const TensorInfo& output,
681 const ComparisonDescriptor& descriptor,
682 Optional<std::string&> reasonIfUnsupported) const
683{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100684
Teresa Charlincedd34f2020-03-30 11:17:30 +0100685 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
686 reasonIfUnsupported,
687 input0,
688 input1,
689 output,
690 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100691}
692
Jim Flynn906f9462019-05-10 13:55:21 +0100693bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
694 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000695 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100696 Optional<std::string&> reasonIfUnsupported) const
697{
Jim Flynne242f2d2019-05-22 14:24:13 +0100698 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
699 {
700 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
701 return false;
702 }
703
704 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
705 if(concatInnerAxis < 3) // Width, height, or channels
706 {
707 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
708 reasonIfUnsupported,
709 inputs,
710 output,
711 descriptor);
712 }
713 else if (concatInnerAxis == 3)
714 {
715 for (auto& input : inputs)
716 {
717 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
718 {
719 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
720 return false;
721 }
722 }
723 return true; // Sub-tensors support concat along batch
724 }
725 else // > 4 dimensions not supported.
726 {
727 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
728 return false;
729 }
Jim Flynn906f9462019-05-10 13:55:21 +0100730}
731
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100732bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
733 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000734{
Mike Kelly0886ac42020-04-27 09:55:40 +0100735 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
736 reasonIfUnsupported,
737 output);
telsoa014fcda012018-03-09 14:13:49 +0000738}
739
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100740bool NeonLayerSupport::IsConvertBf16ToFp32Supported(const TensorInfo& input,
741 const TensorInfo& output,
742 Optional<std::string&> reasonIfUnsupported) const
743{
744 armnn::IgnoreUnused(input);
745 armnn::IgnoreUnused(output);
746 armnn::IgnoreUnused(reasonIfUnsupported);
747 return true;
748}
749
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100750bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
751 const TensorInfo& output,
752 Optional<std::string&> reasonIfUnsupported) const
753{
Jan Eilers8eb25602020-03-09 12:13:48 +0000754 armnn::IgnoreUnused(input);
755 armnn::IgnoreUnused(output);
756 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100757 return true;
758}
759
Narumol Prangnawarat250d3922020-03-30 16:11:04 +0100760bool NeonLayerSupport::IsConvertFp32ToBf16Supported(const TensorInfo& input,
761 const TensorInfo& output,
762 Optional<std::string&> reasonIfUnsupported) const
763{
764 armnn::IgnoreUnused(input);
765 armnn::IgnoreUnused(output);
766 armnn::IgnoreUnused(reasonIfUnsupported);
767 return true;
768}
769
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100770bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
771 const TensorInfo& output,
772 Optional<std::string&> reasonIfUnsupported) const
773{
Jan Eilers8eb25602020-03-09 12:13:48 +0000774 armnn::IgnoreUnused(input);
775 armnn::IgnoreUnused(output);
776 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100777 return true;
778}
779
780bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
781 const TensorInfo& output,
782 const Convolution2dDescriptor& descriptor,
783 const TensorInfo& weights,
784 const Optional<TensorInfo>& biases,
785 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000786{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100787 bool isFastMathEnabled = false;
788#if defined(ARMCOMPUTENEON_ENABLED)
789 if (m_ModelContextPtr)
790 {
791 if (m_ModelContextPtr.get() != nullptr)
792 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100793 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100794 if (modelOptions)
795 {
796 isFastMathEnabled = modelOptions->IsFastMathEnabled();
797 }
798 }
799 }
800#endif
801
surmeh013537c2c2018-05-18 16:31:43 +0100802 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
803 reasonIfUnsupported,
804 input,
805 output,
806 descriptor,
807 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100808 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000809 isFastMathEnabled,
810 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000811}
812
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100813bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
814 const TensorInfo& output,
815 const Convolution3dDescriptor& descriptor,
816 const TensorInfo& weights,
817 const Optional<TensorInfo>& biases,
818 Optional<std::string&> reasonIfUnsupported) const
819{
820 bool isFastMathEnabled = false;
821#if defined(ARMCOMPUTENEON_ENABLED)
822 if (m_ModelContextPtr)
823 {
824 if (m_ModelContextPtr.get() != nullptr)
825 {
826 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
827 if (modelOptions)
828 {
829 isFastMathEnabled = modelOptions->IsFastMathEnabled();
830 }
831 }
832 }
833#endif
834
835 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
836 reasonIfUnsupported,
837 input,
838 output,
839 descriptor,
840 weights,
841 biases,
842 isFastMathEnabled,
843 nullptr);
844}
845
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100846bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
847 const TensorInfo& output,
848 const DepthToSpaceDescriptor& descriptor,
849 Optional<std::string&> reasonIfUnsupported) const
850{
851 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
852 reasonIfUnsupported,
853 input,
854 output,
855 descriptor);
856}
857
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100858bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
859 const TensorInfo& output,
860 const DepthwiseConvolution2dDescriptor& descriptor,
861 const TensorInfo& weights,
862 const Optional<TensorInfo>& biases,
863 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000864{
telsoa01c577f2c2018-08-31 09:22:23 +0100865 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
866 reasonIfUnsupported,
867 input,
868 output,
869 descriptor,
870 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +0000871 biases,
872 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000873}
874
Narumol Prangnawarat01961a72019-05-30 16:47:12 +0100875bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
876 const TensorInfo& output,
877 Optional<std::string&> reasonIfUnsupported) const
878{
879 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
880 reasonIfUnsupported,
881 input,
882 output);
883}
884
Pablo Tellof0bd6832019-04-26 17:58:13 +0100885bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
886 const TensorInfo& output,
887 const DepthwiseConvolution2dDescriptor& descriptor,
888 const TensorInfo& weights,
889 const Optional<TensorInfo>& biases,
890 Optional<std::string&> reasonIfUnsupported) const
891{
892 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
893 reasonIfUnsupported,
894 input,
895 output,
896 descriptor,
897 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +0000898 biases,
899 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +0100900}
901
josh minor4a3c6102020-01-06 16:40:46 -0600902bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
903 const TensorInfo& output,
904 const ElementwiseUnaryDescriptor& descriptor,
905 Optional<std::string&> reasonIfUnsupported) const
906{
Derek Lambertic77874a2020-04-28 13:34:56 +0100907 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -0600908 {
Derek Lambertic77874a2020-04-28 13:34:56 +0100909 case UnaryOperation::Abs:
910 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
911 reasonIfUnsupported,
912 input,
913 output);
914 case UnaryOperation::Exp:
915 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
916 reasonIfUnsupported,
917 input,
918 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +0100919 case UnaryOperation::LogicalNot:
920 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
921 reasonIfUnsupported,
922 input,
923 output);
924 case UnaryOperation::Log:
925 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
926 reasonIfUnsupported,
927 input,
928 output);
Derek Lambertic77874a2020-04-28 13:34:56 +0100929 case UnaryOperation::Neg:
930 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
931 reasonIfUnsupported,
932 input,
933 output);
934 case UnaryOperation::Rsqrt:
935 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
936 reasonIfUnsupported,
937 input,
938 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +0000939 case UnaryOperation::Sin:
940 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
941 reasonIfUnsupported,
942 input,
943 output);
Derek Lambertic77874a2020-04-28 13:34:56 +0100944 default:
945 return false;
josh minor4a3c6102020-01-06 16:40:46 -0600946 }
josh minor4a3c6102020-01-06 16:40:46 -0600947}
948
Teresa Charlin4b10fef2020-07-29 09:36:41 +0100949bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
950 const TensorInfo& output,
951 const FillDescriptor& descriptor,
952 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +0100953{
Teresa Charlin4b10fef2020-07-29 09:36:41 +0100954 armnn::IgnoreUnused(input);
955 armnn::IgnoreUnused(output);
956 armnn::IgnoreUnused(descriptor);
957
958 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +0100959}
960
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100961bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
962 const TensorInfo& output,
963 Optional<std::string&> reasonIfUnsupported) const
964{
Jan Eilers8eb25602020-03-09 12:13:48 +0000965 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100966 return IsNeonBackendSupported(reasonIfUnsupported) &&
967 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
968 input.GetDataType(),
969 &FalseFuncF16<>,
970 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +0000971 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000972 &FalseFuncI32<>,
973 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100974}
975
976bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
977 const TensorInfo& output,
978 const TensorInfo& weights,
979 const TensorInfo& biases,
980 const FullyConnectedDescriptor& descriptor,
981 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000982{
telsoa01c577f2c2018-08-31 09:22:23 +0100983 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
984 reasonIfUnsupported,
985 input,
986 output,
987 weights,
988 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000989 descriptor,
990 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000991}
992
Teresa Charlinf540eb82020-04-10 19:24:55 +0100993bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
994 const TensorInfo& input1,
995 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +0100996 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +0100997 Optional<std::string&> reasonIfUnsupported) const
998{
999 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1000 reasonIfUnsupported,
1001 input0,
1002 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001003 output,
1004 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001005}
1006
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001007bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1008 const TensorInfo& input1,
1009 const TensorInfo& output,
1010 Optional<std::string&> reasonIfUnsupported) const
1011{
1012 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1013 reasonIfUnsupported,
1014 input0,
1015 input1,
1016 output);
1017}
1018
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001019bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1020 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001021{
Derek Lamberti901ea112019-12-10 22:07:09 +00001022 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001023}
1024
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001025bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1026 const TensorInfo& output,
1027 const InstanceNormalizationDescriptor& descriptor,
1028 Optional<std::string&> reasonIfUnsupported) const
1029{
1030 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1031 reasonIfUnsupported,
1032 input,
1033 output,
1034 descriptor);
1035}
1036
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001037bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1038 const TensorInfo& output,
1039 const L2NormalizationDescriptor& descriptor,
1040 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001041{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001042 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001043}
1044
James Conroy177df1e2020-11-13 10:18:51 +00001045bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1046 const TensorInfo& input1,
1047 const TensorInfo& output,
1048 const LogicalBinaryDescriptor& descriptor,
1049 Optional<std::string&> reasonIfUnsupported) const
1050{
1051 switch(descriptor.m_Operation)
1052 {
1053 case LogicalBinaryOperation::LogicalAnd:
1054 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1055 reasonIfUnsupported,
1056 input0,
1057 input1,
1058 output);
1059 case LogicalBinaryOperation::LogicalOr:
1060 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1061 reasonIfUnsupported,
1062 input0,
1063 input1,
1064 output);
1065 default:
1066 return false;
1067 }
1068}
1069
Keith Davis69e653f2020-07-02 11:49:26 +01001070bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1071 const TensorInfo& output,
1072 const LogSoftmaxDescriptor& descriptor,
1073 Optional<std::string&> reasonIfUnsupported) const
1074{
1075 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1076}
1077
Jan Eilersad5293a2019-07-08 09:57:55 +01001078bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1079 const TensorInfo& outputStateIn,
1080 const TensorInfo& cellStateIn,
1081 const TensorInfo& scratchBuffer,
1082 const TensorInfo& outputStateOut,
1083 const TensorInfo& cellStateOut,
1084 const TensorInfo& output,
1085 const LstmDescriptor& descriptor,
1086 const LstmInputParamsInfo& paramsInfo,
1087 Optional<std::string&> reasonIfUnsupported) const
1088{
1089 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1090 reasonIfUnsupported,
1091 input,
1092 outputStateIn,
1093 cellStateIn,
1094 scratchBuffer,
1095 outputStateOut,
1096 cellStateOut,
1097 output,
1098 descriptor,
1099 paramsInfo);
1100}
1101
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001102bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1103 const TensorInfo& input1,
1104 const TensorInfo& output,
1105 Optional<std::string&> reasonIfUnsupported) const
1106{
1107 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1108 reasonIfUnsupported,
1109 input0,
1110 input1,
1111 output);
1112}
1113
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001114bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1115 const TensorInfo& output,
1116 const MeanDescriptor& descriptor,
1117 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001118{
Matthew Benthamfd899962018-12-31 15:49:42 +00001119 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1120 reasonIfUnsupported,
1121 input,
1122 output,
1123 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001124}
1125
Conor Kennedy54b21692019-01-09 07:57:38 +00001126bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1127 const TensorInfo& input1,
1128 const TensorInfo& output,
1129 Optional<std::string&> reasonIfUnsupported) const
1130{
1131 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1132 reasonIfUnsupported,
1133 input0,
1134 input1,
1135 output);
1136}
1137
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001138bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1139 const TensorInfo& input1,
1140 const TensorInfo& output,
1141 Optional<std::string&> reasonIfUnsupported) const
1142{
1143 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1144 reasonIfUnsupported,
1145 input0,
1146 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001147 output,
1148 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001149}
1150
Pablo Telloe61f0712020-01-23 10:37:17 +00001151bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1152 const TensorInfo& input1,
1153 const TensorInfo& output,
1154 Optional<std::string&> reasonIfUnsupported) const
1155{
1156 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1157 reasonIfUnsupported,
1158 input0,
1159 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001160 output,
1161 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001162}
1163
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001164bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1165 const TensorInfo& output,
1166 const NormalizationDescriptor& descriptor,
1167 Optional<std::string&> reasonIfUnsupported) const
1168{
1169 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1170 reasonIfUnsupported,
1171 input,
1172 output,
1173 descriptor);
1174}
1175
1176bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1177 Optional<std::string&> reasonIfUnsupported) const
1178{
Derek Lamberti901ea112019-12-10 22:07:09 +00001179 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001180}
1181
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001182bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1183 const TensorInfo& output,
1184 const PadDescriptor& descriptor,
1185 Optional<std::string&> reasonIfUnsupported) const
1186{
1187 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1188 reasonIfUnsupported,
1189 input,
1190 output,
1191 descriptor);
1192}
1193
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001194bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1195 const TensorInfo& output,
1196 const PermuteDescriptor& descriptor,
1197 Optional<std::string&> reasonIfUnsupported) const
1198{
1199 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001200}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001201
1202bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1203 const TensorInfo& output,
1204 const Pooling2dDescriptor& descriptor,
1205 Optional<std::string&> reasonIfUnsupported) const
1206{
1207 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1208}
1209
Nikhil Raj9b461482019-07-03 15:58:31 +01001210bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1211 const armnn::TensorInfo &alpha,
1212 const armnn::TensorInfo &output,
1213 armnn::Optional<std::string &> reasonIfUnsupported) const
1214{
1215 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1216}
1217
James Conroycc340932020-05-12 18:08:52 +01001218bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1219 const TensorInfo& previousOutputIn,
1220 const TensorInfo& previousCellStateIn,
1221 const TensorInfo& outputStateOut,
1222 const TensorInfo& cellStateOut,
1223 const TensorInfo& output,
1224 const QLstmDescriptor& descriptor,
1225 const LstmInputParamsInfo& paramsInfo,
1226 Optional<std::string&> reasonIfUnsupported) const
1227{
1228 // Check required here in order to pass IsLayerSupported for datatypes tests
1229 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1230 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1231 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1232 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1233 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1234 output.GetDataType() == armnn::DataType::QAsymmS8)
1235 {
1236 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1237 reasonIfUnsupported,
1238 input,
1239 previousCellStateIn,
1240 previousOutputIn,
1241 cellStateOut,
1242 outputStateOut,
1243 output,
1244 descriptor,
1245 paramsInfo);
1246 }
1247 else
1248 {
1249 return false;
1250 }
1251}
1252
Sadik Armaganfabc2892019-05-31 09:05:11 +01001253bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1254 const TensorInfo& output,
1255 Optional<std::string&> reasonIfUnsupported) const
1256{
1257 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1258 reasonIfUnsupported,
1259 input,
1260 output);
1261}
1262
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001263bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1264 const TensorInfo& cellStateIn,
1265 const TensorInfo& outputStateIn,
1266 const TensorInfo& cellStateOut,
1267 const TensorInfo& outputStateOut,
1268 const QuantizedLstmInputParamsInfo& paramsInfo,
1269 Optional<std::string&> reasonIfUnsupported) const
1270{
1271 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1272 reasonIfUnsupported,
1273 input,
1274 cellStateIn,
1275 outputStateIn,
1276 cellStateOut,
1277 outputStateOut,
1278 paramsInfo);
1279}
1280
Sadik Armagana2747482021-02-09 10:28:54 +00001281bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1282 const TensorInfo& output,
1283 const ReduceDescriptor& descriptor,
1284 Optional<std::string&> reasonIfUnsupported) const
1285{
1286 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1287 reasonIfUnsupported,
1288 input,
1289 output,
1290 descriptor);
1291}
1292
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001293bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001294 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001295 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001296 Optional<std::string&> reasonIfUnsupported) const
1297{
Jan Eilers8eb25602020-03-09 12:13:48 +00001298 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001299 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1300 reasonIfUnsupported,
1301 input,
1302 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001303}
1304
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001305bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1306 const TensorInfo& output,
1307 const ResizeDescriptor& descriptor,
1308 Optional<std::string&> reasonIfUnsupported) const
1309{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001310 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1311 reasonIfUnsupported,
1312 input,
1313 output,
1314 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001315}
1316
josh minor036f02d2019-11-15 14:53:22 -06001317bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1318 const TensorInfo& output,
1319 const SliceDescriptor& descriptor,
1320 Optional<std::string&> reasonIfUnsupported) const
1321{
1322 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1323 reasonIfUnsupported,
1324 input,
1325 output,
1326 descriptor);
1327}
1328
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001329bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1330 const TensorInfo& output,
1331 const SoftmaxDescriptor& descriptor,
1332 Optional<std::string&> reasonIfUnsupported) const
1333{
1334 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1335}
1336
Mike Kelly0be3a882020-01-24 11:27:50 +00001337bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1338 const TensorInfo& output,
1339 const SpaceToBatchNdDescriptor& descriptor,
1340 Optional<std::string&> reasonIfUnsupported) const
1341{
1342 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1343 reasonIfUnsupported,
1344 input,
1345 output,
1346 descriptor);
1347}
1348
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001349bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001350 const TensorInfo& output,
1351 const SpaceToDepthDescriptor& descriptor,
1352 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001353{
1354 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1355 reasonIfUnsupported,
1356 input,
1357 output,
1358 descriptor);
1359}
1360
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001361bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001362 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1363 const ViewsDescriptor& descriptor,
1364 Optional<std::string&> reasonIfUnsupported) const
1365{
1366#if defined(ARMCOMPUTENEON_ENABLED)
1367 // Split along the last dimension, cannot use sub-tensors
1368 // as width and height of the sub-tensors do not match
1369 // the width and height of the parent tensor
1370 // in case of input with more than 2D.
1371 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1372 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1373 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1374 {
1375 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1376 reasonIfUnsupported,
1377 input,
1378 outputs,
1379 *splitAxis.begin());
1380 }
1381#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001382 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001383 for (auto output : outputs)
1384 {
1385 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1386 {
1387 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1388 return false;
1389 }
1390 }
1391 return true;
1392}
1393
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001394bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1395 const TensorInfo& output,
1396 const StackDescriptor& descriptor,
1397 Optional<std::string&> reasonIfUnsupported) const
1398{
1399 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1400 reasonIfUnsupported,
1401 inputs,
1402 output,
1403 descriptor);
1404}
1405
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001406bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1407 const TensorInfo& output,
1408 const StridedSliceDescriptor& descriptor,
1409 Optional<std::string&> reasonIfUnsupported) const
1410{
1411 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1412 reasonIfUnsupported,
1413 input,
1414 output,
1415 descriptor);
1416}
1417
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001418bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1419 const TensorInfo& input1,
1420 const TensorInfo& output,
1421 Optional<std::string&> reasonIfUnsupported) const
1422{
1423 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1424 reasonIfUnsupported,
1425 input0,
1426 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001427 output,
1428 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001429}
1430
Sadik Armagan581742d2019-08-12 14:11:37 +01001431bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1432 const TensorInfo& output,
1433 const TransposeConvolution2dDescriptor& descriptor,
1434 const TensorInfo& weights,
1435 const Optional<TensorInfo>& biases,
1436 Optional<std::string&> reasonIfUnsupported) const
1437{
1438 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1439 reasonIfUnsupported,
1440 input,
1441 output,
1442 descriptor,
1443 weights,
1444 biases);
1445}
1446
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001447bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1448 const TensorInfo& output,
1449 const TransposeDescriptor& descriptor,
1450 Optional<std::string&> reasonIfUnsupported) const
1451{
1452 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1453}
1454
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001455bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1456 const TensorInfo& outputStateIn,
1457 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001458 const TensorInfo& outputStateOut,
1459 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001460 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001461 const UnidirectionalSequenceLstmDescriptor& descriptor,
1462 const LstmInputParamsInfo& paramsInfo,
1463 Optional<std::string&> reasonIfUnsupported) const
1464{
Mike Kelly12994962022-04-21 11:57:09 +01001465 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1466 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1467 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1468 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1469 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1470 output.GetDataType() == armnn::DataType::QAsymmS8)
1471 {
1472 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1473 reasonIfUnsupported,
1474 input,
1475 outputStateIn,
1476 cellStateIn,
1477 outputStateOut,
1478 cellStateOut,
1479 output,
1480 descriptor,
1481 paramsInfo);
1482 }
1483 else
1484 {
1485 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1486 reasonIfUnsupported,
1487 input,
1488 outputStateIn,
1489 cellStateIn,
1490 outputStateOut,
1491 cellStateOut,
1492 output,
1493 descriptor,
1494 paramsInfo);
1495 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001496}
1497
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001498} // namespace armnn