blob: ef1d21835ab9d21363b9b62181a6f261caebd3a6 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
Mike Kelly3ec30772023-03-08 13:47:17 +00002// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5
6#include "NeonLayerSupport.hpp"
Sadik Armagan045f6be2020-09-10 13:37:32 +01007#include "NeonBackendModelContext.hpp"
telsoa014fcda012018-03-09 14:13:49 +00008
Derek Lambertic77874a2020-04-28 13:34:56 +01009#include <armnn/Exceptions.hpp>
telsoa014fcda012018-03-09 14:13:49 +000010#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010011#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000012#include <armnn/BackendRegistry.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
Matteo Martincighc601aa62019-10-29 15:03:22 +000014#include <LayerSupportCommon.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000015#include <armnn/utility/IgnoreUnused.hpp>
Sadik Armagan045f6be2020-09-10 13:37:32 +010016#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
Matteo Martincighd95e9062019-01-31 15:35:59 +000018#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010019#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar710f6642019-11-27 14:48:32 +000020#include <aclCommon/ArmComputeTensorUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010021#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000022#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010023#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010024#include "workloads/NeonArgMinMaxWorkload.hpp"
Teresa Charlin0f86ecf2022-10-13 15:47:08 +010025#include "workloads/NeonBatchMatMulWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000026#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000027#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010028#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010029#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010030#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010031#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010032#include "workloads/NeonConstantWorkload.hpp"
Matthew Bentham34336f92023-04-27 12:13:50 +000033#include "workloads/NeonConvertFp16ToFp32Workload.hpp"
34#include "workloads/NeonConvertFp32ToFp16Workload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010035#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010036#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010037#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010038#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010039#include "workloads/NeonDequantizeWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010040#include "workloads/NeonDivisionWorkload.hpp"
John Mcloughlin34c1c382023-05-17 15:08:36 +010041#include "workloads/NeonElementwiseBinaryWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010042#include "workloads/NeonExpWorkload.hpp"
Teresa Charlin9145e382023-08-17 18:44:58 +010043#include "workloads/NeonFullyConnectedWorkload.hpp"
44#include "workloads/NeonFusedWorkload.hpp"
45#include "workloads/NeonGatherWorkload.hpp"
46#include "workloads/NeonGatherNdWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010047#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010048#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010049#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010050#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000051#include "workloads/NeonLogicalAndWorkload.hpp"
52#include "workloads/NeonLogicalNotWorkload.hpp"
53#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010054#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000055#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000056#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000057#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000058#include "workloads/NeonMultiplicationWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000059#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010060#include "workloads/NeonNormalizationFloatWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000061#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010062#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010063#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010064#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010065#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010066#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010067#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010068#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000069#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000070#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010071#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010072#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010073#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060074#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010075#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000076#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010077#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010078#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010079#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010080#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010081#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000082#include "workloads/NeonSubtractionWorkload.hpp"
David Monahan36e6eae2023-07-26 18:37:45 +010083#include "workloads/NeonTileWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010084#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000085#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000086#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010087#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000088#endif
89
telsoa014fcda012018-03-09 14:13:49 +000090namespace armnn
91{
telsoa014fcda012018-03-09 14:13:49 +000092
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010093namespace
arovir017ff76c52018-10-09 09:40:58 +010094{
telsoa014fcda012018-03-09 14:13:49 +000095
Cathal Corbett80f71a82022-12-20 18:25:40 +000096const TensorInfo OverrideDataType(const TensorInfo& info, Optional<DataType> type)
97{
98 if (!type)
99 {
100 return info;
101 }
102 return TensorInfo(info.GetShape(),
103 type.value(),
104 info.GetQuantizationScale(),
105 info.GetQuantizationOffset(),
106 info.IsConstant());
107}
108
Derek Lamberti901ea112019-12-10 22:07:09 +0000109template< typename ... Args>
110bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +0000111{
Jan Eilers8eb25602020-03-09 12:13:48 +0000112 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +0000113#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000114 return true;
115#else
Derek Lamberti0790dce2019-04-15 18:37:35 +0100116 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +0000117 return false;
118#endif
119}
120
telsoa01c577f2c2018-08-31 09:22:23 +0100121template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100122bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000123 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100124 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000125 Uint8Func uint8FuncPtr,
126 Params&&... params)
127{
128 return IsNeonBackendSupported(reasonIfUnsupported) &&
129 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
Teresa Charlin9145e382023-08-17 18:44:58 +0100130 dataType,
131 floatFuncPtr,
132 floatFuncPtr,
133 uint8FuncPtr,
134 &FalseFunc<>,
135 &FalseFunc<>,
136 std::forward<Params>(params)...);
telsoa014fcda012018-03-09 14:13:49 +0000137}
138
Matteo Martincighd95e9062019-01-31 15:35:59 +0000139#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000140template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100141inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000142{
143 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
144 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
145 if (!supported && reasonIfUnsupported)
146 {
arovir01085f0a42018-10-08 14:48:19 +0100147 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000148 }
149 return supported;
150}
151
152#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
153 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
154#else
155#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000156 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000157#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100158} // anonymous namespace
159
Sadik Armagan045f6be2020-09-10 13:37:32 +0100160NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
161 : m_ModelContextPtr(modelContextPtr)
162{
163}
164
165NeonLayerSupport::NeonLayerSupport()
166 : m_ModelContextPtr(nullptr)
167{
168}
169
Cathal Corbett80f71a82022-12-20 18:25:40 +0000170bool IsLayerTypeSupported(const LayerType& type,
171 const std::vector<TensorInfo>& infos,
172 const BaseDescriptor& descriptor,
173 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
174 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
175 Optional<std::string&> reasonIfUnsupported,
176 const NeonLayerSupport& support)
Cathal Corbett34b429c2021-12-24 12:24:40 +0000177{
178 switch (type)
179 {
180 case LayerType::Activation:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000181 return support.IsActivationSupported(infos[0],
182 infos[1],
183 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
184 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000185 case LayerType::Addition:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000186 return support.IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000187 case LayerType::ArgMinMax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000188 return support.IsArgMinMaxSupported(infos[0],
189 infos[1],
190 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
191 reasonIfUnsupported);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100192 case LayerType::BatchMatMul:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000193 return support.IsBatchMatMulSupported(infos[0],
194 infos[1],
195 infos[2],
196 *(PolymorphicDowncast<const BatchMatMulDescriptor*>(&descriptor)),
197 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000198 case LayerType::BatchNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000199 return support.IsBatchNormalizationSupported(infos[0],
200 infos[1],
201 infos[2],
202 infos[3],
203 infos[4],
204 infos[5],
205 *(PolymorphicDowncast<const
206 BatchNormalizationDescriptor*>(&descriptor)),
207 reasonIfUnsupported);
208 case LayerType::BatchToSpaceNd:
209 return support.IsBatchToSpaceNdSupported(infos[0],
210 infos[1],
211 *(PolymorphicDowncast<const
212 BatchToSpaceNdDescriptor*>(&descriptor)),
213 reasonIfUnsupported);
214 case LayerType::Cast:
215 return support.IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
216 case LayerType::ChannelShuffle:
217 return support.IsChannelShuffleSupported(infos[0],
218 infos[1],
219 *(PolymorphicDowncast<const
220 ChannelShuffleDescriptor*>(&descriptor)),
221 reasonIfUnsupported);
222 case LayerType::Comparison:
223 return support.IsComparisonSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000224 infos[1],
225 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000226 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000227 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000228 case LayerType::Concat:
229 {
230 std::vector<const TensorInfo*> inputInfos;
231 for (uint32_t i = 0; i < (infos.size() - 1); i++)
232 {
233 inputInfos.push_back(&infos[i]);
234 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000235 return support.IsConcatSupported(inputInfos,
236 infos[infos.size() - 1],
237 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
238 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000239 }
240 case LayerType::Constant:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000241 return support.IsConstantSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000242 case LayerType::ConvertFp16ToFp32:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000243 return support.IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000244 case LayerType::ConvertFp32ToFp16:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000245 return support.IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000246 case LayerType::Convolution2d:
247 {
248 if (infos.size() != 4)
249 {
250 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
251 "TensorInfos should be of format: {input, output, weights, biases}.");
252 }
253
254 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
255 if (infos[3] == TensorInfo())
256 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000257 return support.IsConvolution2dSupported(infos[0],
258 infos[1],
259 desc,
260 infos[2],
261 EmptyOptional(),
262 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000263 }
264 else
265 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000266 return support.IsConvolution2dSupported(infos[0],
267 infos[1],
268 desc,
269 infos[2],
270 infos[3],
271 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000272 }
273 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000274 case LayerType::Convolution3d:
275 {
276 if (infos.size() != 4)
277 {
278 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
279 "TensorInfos should be of format: {input, output, weights, biases}.");
280 }
281
282 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
283 if (infos[3] == TensorInfo())
284 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000285 return support.IsConvolution3dSupported(infos[0],
286 infos[1],
287 desc,
288 infos[2],
289 EmptyOptional(),
290 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000291 }
292 else
293 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000294 return support.IsConvolution3dSupported(infos[0],
295 infos[1],
296 desc,
297 infos[2],
298 infos[3],
299 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000300 }
301 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000302 case LayerType::DepthToSpace:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000303 return support.IsDepthToSpaceSupported(infos[0],
304 infos[1],
305 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
306 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000307 case LayerType::DepthwiseConvolution2d:
308 {
309 if (infos.size() != 4)
310 {
311 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
312 "TensorInfos should be of format: {input, output, weights, biases}.");
313 }
314
315 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
316 if (infos[3] == TensorInfo())
317 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000318 return support.IsDepthwiseConvolutionSupported(infos[0],
319 infos[1],
320 desc,
321 infos[2],
322 EmptyOptional(),
323 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000324 }
325 else
326 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000327 return support.IsDepthwiseConvolutionSupported(infos[0],
328 infos[1],
329 desc,
330 infos[2],
331 infos[3],
332 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000333 }
334 }
335 case LayerType::Dequantize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000336 return support.IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000337 case LayerType::DetectionPostProcess:
338 {
339 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
Cathal Corbett80f71a82022-12-20 18:25:40 +0000340 return support.IsDetectionPostProcessSupported(infos[0],
341 infos[1],
342 infos[2],
343 infos[3],
344 infos[4],
345 infos[5],
346 infos[6],
347 desc,
348 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000349 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000350 case LayerType::Division:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000351 return support.IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Mike Kelly3ec30772023-03-08 13:47:17 +0000352 case LayerType::ElementwiseBinary:
353 {
354 auto desc = *(PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor));
355
356 switch (desc.m_Operation)
357 {
358 case BinaryOperation::Add:
359 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
360 reasonIfUnsupported,
361 infos[0],
362 infos[1],
363 infos[2],
364 nullptr);
365 case BinaryOperation::Div:
366 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
367 reasonIfUnsupported,
368 infos[0],
369 infos[1],
370 infos[2],
371 nullptr);
372 case BinaryOperation::Maximum:
373 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
374 reasonIfUnsupported,
375 infos[0],
376 infos[1],
377 infos[2]);
378 case BinaryOperation::Minimum:
379 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
380 reasonIfUnsupported,
381 infos[0],
382 infos[1],
383 infos[2]);
384 case BinaryOperation::Mul:
385 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
386 reasonIfUnsupported,
387 infos[0],
388 infos[1],
389 infos[2],
390 nullptr);
John Mcloughlin34c1c382023-05-17 15:08:36 +0100391 case BinaryOperation::Power:
392 case BinaryOperation::SqDiff:
393 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonElementwiseBinaryWorkloadValidate,
394 reasonIfUnsupported,
395 infos[0],
396 infos[1],
397 infos[2],
398 desc,
399 nullptr);
Mike Kelly3ec30772023-03-08 13:47:17 +0000400 case BinaryOperation::Sub:
401 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
402 reasonIfUnsupported,
403 infos[0],
404 infos[1],
405 infos[2],
406 nullptr);
407 default:
408 return false;
409 }
410 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000411 case LayerType::ElementwiseUnary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000412 return support.IsElementwiseUnarySupported(infos[0],
413 infos[1],
414 *(PolymorphicDowncast<const
415 ElementwiseUnaryDescriptor*>(&descriptor)),
416 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000417 case LayerType::Fill:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000418 return support.IsFillSupported(infos[0],
419 infos[1],
420 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
421 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000422 case LayerType::Floor:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000423 return support.IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000424 case LayerType::FullyConnected:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000425 return support.IsFullyConnectedSupported(infos[0],
426 infos[1],
427 infos[2],
428 infos[3],
429 *(PolymorphicDowncast<const
430 FullyConnectedDescriptor*>(&descriptor)),
431 reasonIfUnsupported);
Teresa Charlin9145e382023-08-17 18:44:58 +0100432 case LayerType::Fused:
433 {
434 auto fusedDescriptor = *(PolymorphicDowncast<const FusedDescriptor*>(&descriptor));
435 if (fusedDescriptor.m_NumInputSlots + fusedDescriptor.m_NumOutputSlots != infos.size())
436 {
437 throw InvalidArgumentException("Invalid number of FusedLayer TensorInfos.");
438 }
439
440 std::vector<TensorInfo> inputInfos(infos.begin(), infos.begin() + fusedDescriptor.m_NumInputSlots);
441 std::vector<TensorInfo> outputInfos(infos.begin() + fusedDescriptor.m_NumInputSlots, infos.end());
442
443 return support.IsFusedSupported({inputInfos.begin(), inputInfos.end()},
444 {outputInfos.begin(), outputInfos.end()},
445 fusedDescriptor,
446 reasonIfUnsupported);
447 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000448 case LayerType::Gather:
449 return support.IsGatherSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000450 infos[1],
451 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000452 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000453 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100454 case LayerType::GatherNd:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000455 return support.IsGatherNdSupported(infos[0],
456 infos[1],
457 infos[2],
458 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000459 case LayerType::Input:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000460 return support.IsInputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000461 case LayerType::InstanceNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000462 return support.IsInstanceNormalizationSupported(infos[0],
463 infos[1],
464 *(PolymorphicDowncast<const
465 InstanceNormalizationDescriptor*>(&descriptor)),
466 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000467 case LayerType::L2Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000468 return support.IsL2NormalizationSupported(infos[0],
469 infos[1],
470 *(PolymorphicDowncast<const
471 L2NormalizationDescriptor*>(&descriptor)),
472 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000473 case LayerType::LogicalBinary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000474 return support.IsLogicalBinarySupported(infos[0],
475 infos[1],
476 infos[2],
477 *(PolymorphicDowncast<const
478 LogicalBinaryDescriptor*>(&descriptor)),
479 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000480 case LayerType::LogSoftmax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000481 return support.IsLogSoftmaxSupported(infos[0],
482 infos[1],
483 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
484 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000485 case LayerType::Lstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000486 return support.IsLstmSupported(infos[0],
487 infos[1],
488 infos[2],
489 infos[3],
490 infos[4],
491 infos[5],
492 infos[6],
493 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
494 lstmParamsInfo.value(),
495 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000496 case LayerType::Map:
497 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000498 case LayerType::Maximum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000499 return support.IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000500 case LayerType::Mean:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000501 return support.IsMeanSupported(infos[0],
502 infos[1],
503 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
504 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000505 case LayerType::MemCopy:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000506 return support.IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000507 case LayerType::MemImport:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000508 return support.IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000509 case LayerType::Merge:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000510 return support.IsMergeSupported(infos[0],
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000511 infos[1],
512 infos[2],
513 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000514 case LayerType::Minimum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000515 return support.IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000516 case LayerType::Multiplication:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000517 return support.IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000518 case LayerType::Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000519 return support.IsNormalizationSupported(infos[0],
520 infos[1],
521 *(PolymorphicDowncast<const
522 NormalizationDescriptor*>(&descriptor)),
523 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000524 case LayerType::Output:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000525 return support.IsOutputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000526 case LayerType::Pad:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000527 return support.IsPadSupported(infos[0],
528 infos[1],
529 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
530 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000531 case LayerType::Permute:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000532 return support.IsPermuteSupported(infos[0],
533 infos[1],
534 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
535 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000536 case LayerType::Pooling2d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000537 return support.IsPooling2dSupported(infos[0],
538 infos[1],
539 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
540 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100541 case LayerType::Pooling3d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000542 return support.IsPooling3dSupported(infos[0],
543 infos[1],
544 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
545 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000546 case LayerType::Prelu:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000547 return support.IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000548 case LayerType::QLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000549 return support.IsQLstmSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000550 infos[1],
551 infos[2],
552 infos[3],
553 infos[4],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000554 infos[5],
555 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
556 lstmParamsInfo.value(),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000557 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000558 case LayerType::Quantize:
559 return support.IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
560 case LayerType::QuantizedLstm:
561 return support.IsQuantizedLstmSupported(infos[0],
562 infos[1],
563 infos[2],
564 infos[3],
565 infos[4],
566 quantizedLstmParamsInfo.value(),
567 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000568 case LayerType::Rank:
569 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000570 case LayerType::Reshape:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000571 return support.IsReshapeSupported(infos[0],
572 infos[1],
573 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
574 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000575 case LayerType::Resize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000576 return support.IsResizeSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000577 infos[1],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000578 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000579 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000580 case LayerType::Reduce:
581 return support.IsReduceSupported(infos[0],
582 infos[1],
583 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
584 reasonIfUnsupported);
585 case LayerType::Shape:
586 return support.IsShapeSupported(infos[0],
587 infos[1],
588 reasonIfUnsupported);
589 case LayerType::Slice:
590 return support.IsSliceSupported(infos[0],
591 infos[1],
592 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
593 reasonIfUnsupported);
594 case LayerType::Softmax:
595 return support.IsSoftmaxSupported(infos[0],
596 infos[1],
597 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
598 reasonIfUnsupported);
599 case LayerType::SpaceToBatchNd:
600 return support.IsSpaceToBatchNdSupported(infos[0],
601 infos[1],
602 *(PolymorphicDowncast<const
603 SpaceToBatchNdDescriptor*>(&descriptor)),
604 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000605 case LayerType::SpaceToDepth:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000606 return support.IsSpaceToDepthSupported(infos[0],
607 infos[1],
608 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
609 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000610 case LayerType::Splitter:
611 {
612 std::vector<TensorInfo> outputInfos;
613 for (uint32_t i = 1; i < infos.size(); i++)
614 {
615 outputInfos.push_back(infos[i]);
616 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000617 return support.IsSplitterSupported(infos[0],
618 {outputInfos.begin(), outputInfos.end()},
619 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
620 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000621 }
622 case LayerType::Stack:
623 {
624 std::vector<const TensorInfo*> inputInfos;
625 for (uint32_t i = 0; i < infos.size() - 1; i++)
626 {
627 inputInfos.push_back(&infos[i]);
628 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000629 return support.IsStackSupported(inputInfos,
630 infos[infos.size() - 1],
631 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
632 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000633 }
634 case LayerType::StridedSlice:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000635 return support.IsStridedSliceSupported(infos[0],
636 infos[1],
637 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
638 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000639 case LayerType::Subtraction:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000640 return support.IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
David Monahan36e6eae2023-07-26 18:37:45 +0100641 case LayerType::Tile:
642 return support.IsTileSupported(infos[0],
643 infos[1],
644 *(PolymorphicDowncast<const TileDescriptor*>(&descriptor)),
645 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000646 case LayerType::Transpose:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000647 return support.IsTransposeSupported(infos[0],
648 infos[1],
649 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
650 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000651 case LayerType::TransposeConvolution2d:
652 {
653 if (infos.size() != 4)
654 {
655 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
656 "TensorInfos should be of format: {input, output, weights, biases}.");
657 }
658
659 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
660 if (infos[3] == TensorInfo())
661 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000662 return support.IsTransposeConvolution2dSupported(infos[0],
663 infos[1],
664 desc,
665 infos[2],
666 EmptyOptional(),
667 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000668 }
669 else
670 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000671 return support.IsTransposeConvolution2dSupported(infos[0],
672 infos[1],
673 desc,
674 infos[2],
675 infos[3],
676 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000677 }
678 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000679 case LayerType::UnidirectionalSequenceLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000680 {
681 auto desc = *(PolymorphicDowncast<const UnidirectionalSequenceLstmDescriptor*>(&descriptor));
682 return support.IsUnidirectionalSequenceLstmSupported(infos[0],
683 infos[1],
684 infos[2],
685 infos[3],
686 infos[4],
687 infos[5],
688 desc,
689 lstmParamsInfo.value(),
690 reasonIfUnsupported);
691 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000692 case LayerType::Unmap:
693 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000694 default:
695 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000696 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100697 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000698 return false;
699 }
700}
701
Cathal Corbett80f71a82022-12-20 18:25:40 +0000702bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
703 const std::vector<TensorInfo>& infos,
704 const BaseDescriptor& descriptor,
705 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
706 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
707 Optional<std::string&> reasonIfUnsupported) const
708{
709 bool isSupported = IsLayerTypeSupported(type,
710 infos,
711 descriptor,
712 lstmParamsInfo,
713 quantizedLstmParamsInfo,
714 reasonIfUnsupported,
715 *this);
716
717 // For android-nn-driver and support library, to run FP16 operations on CpuAcc we need at least v8.2
718 // architecture. If the available architecture is older than v8.2, we can check if the operator is
719 // supported by changing operator inputs & outputs to be FP32.
720 // This does not change the operator datatype in the above parsers to be FP32. We are simply reporting
721 // to the parsers if the operator can supported in ArmNN. We will then re-enter ArmNN (Network.cpp)
722 // where we will recheck IsLayerSupported() on the FP16 datatype, update the operator to be FP32,
723 // and, insert convert layers around the FP32 operator.
724 if (reasonIfUnsupported.has_value())
725 {
726 std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
727 if (!isSupported
728 && reasonIfUnsupported.value().find(checkStr) != std::string::npos)
729 {
730 std::vector<TensorInfo> newInfos;
731 for (auto info: infos)
732 {
733 newInfos.emplace_back(OverrideDataType(info, DataType::Float32));
734 }
735
736 std::string tmpString;
737 return IsLayerTypeSupported(type,
738 newInfos,
739 descriptor,
740 lstmParamsInfo,
741 quantizedLstmParamsInfo,
742 tmpString,
743 *this);
744 }
745 }
746
747 return isSupported;
748}
749
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100750bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
751 const TensorInfo& output,
752 const ActivationDescriptor& descriptor,
753 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000754{
Jan Eilers8eb25602020-03-09 12:13:48 +0000755 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100756 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
757 reasonIfUnsupported,
758 input,
759 output,
760 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000761}
762
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100763bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
764 const TensorInfo& input1,
765 const TensorInfo& output,
766 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000767{
telsoa01c577f2c2018-08-31 09:22:23 +0100768 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
769 reasonIfUnsupported,
770 input0,
771 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000772 output,
773 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000774}
775
James Conroyd47a0642019-09-17 14:22:06 +0100776bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
777 const TensorInfo& output,
778 const ArgMinMaxDescriptor& descriptor,
779 Optional<std::string&> reasonIfUnsupported) const
780{
781 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
782 reasonIfUnsupported,
783 input,
784 output,
785 descriptor);
786}
787
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100788bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
789 const TensorInfo& inputY,
790 const TensorInfo& output,
791 const BatchMatMulDescriptor& descriptor,
792 Optional<std::string&> reasonIfUnsupported) const
793{
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000794 bool isFastMathEnabled = false;
795#if defined(ARMCOMPUTENEON_ENABLED)
796 if (m_ModelContextPtr)
797 {
798 if (m_ModelContextPtr.get() != nullptr)
799 {
800 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
801 if (modelOptions)
802 {
803 isFastMathEnabled = modelOptions->IsFastMathEnabled();
804 }
805 }
806 }
807#endif
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100808 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
809 reasonIfUnsupported,
810 inputX,
811 inputY,
812 output,
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000813 descriptor,
814 isFastMathEnabled,
815 nullptr);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100816}
817
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100818bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
819 const TensorInfo& output,
820 const TensorInfo& mean,
821 const TensorInfo& var,
822 const TensorInfo& beta,
823 const TensorInfo& gamma,
824 const BatchNormalizationDescriptor& descriptor,
825 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000826{
telsoa01c577f2c2018-08-31 09:22:23 +0100827 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
828 reasonIfUnsupported,
829 input,
830 output,
831 mean,
832 var,
833 beta,
834 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000835 descriptor,
836 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000837}
838
Mike Kelly56858022020-01-27 12:14:47 +0000839bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
840 const TensorInfo& output,
841 const BatchToSpaceNdDescriptor& descriptor,
842 Optional<std::string&> reasonIfUnsupported) const
843{
844 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
845 reasonIfUnsupported,
846 input,
847 output,
848 descriptor);
849}
850
Sadik Armagan48f011e2021-04-21 10:50:34 +0100851bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
852 const TensorInfo& output,
853 Optional<std::string&> reasonIfUnsupported) const
854{
855 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
856 reasonIfUnsupported,
857 input,
858 output);
859}
860
Teresa Charline89dd692021-09-01 16:30:34 +0100861bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
862 const TensorInfo& output,
863 const ChannelShuffleDescriptor& descriptor,
864 Optional<std::string&> reasonIfUnsupported) const
865{
866 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
867 reasonIfUnsupported,
868 input,
869 output,
870 descriptor);
871}
872
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100873bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
874 const TensorInfo& input1,
875 const TensorInfo& output,
876 const ComparisonDescriptor& descriptor,
877 Optional<std::string&> reasonIfUnsupported) const
878{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100879
Teresa Charlincedd34f2020-03-30 11:17:30 +0100880 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
881 reasonIfUnsupported,
882 input0,
883 input1,
884 output,
885 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100886}
887
Jim Flynn906f9462019-05-10 13:55:21 +0100888bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
889 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000890 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100891 Optional<std::string&> reasonIfUnsupported) const
892{
Jim Flynne242f2d2019-05-22 14:24:13 +0100893 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
894 {
895 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
896 return false;
897 }
898
899 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
900 if(concatInnerAxis < 3) // Width, height, or channels
901 {
902 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
903 reasonIfUnsupported,
904 inputs,
905 output,
906 descriptor);
907 }
908 else if (concatInnerAxis == 3)
909 {
910 for (auto& input : inputs)
911 {
912 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
913 {
914 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
915 return false;
916 }
917 }
918 return true; // Sub-tensors support concat along batch
919 }
920 else // > 4 dimensions not supported.
921 {
922 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
923 return false;
924 }
Jim Flynn906f9462019-05-10 13:55:21 +0100925}
926
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100927bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
928 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000929{
Mike Kelly0886ac42020-04-27 09:55:40 +0100930 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
931 reasonIfUnsupported,
932 output);
telsoa014fcda012018-03-09 14:13:49 +0000933}
934
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100935bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
936 const TensorInfo& output,
937 Optional<std::string&> reasonIfUnsupported) const
938{
Matthew Bentham34336f92023-04-27 12:13:50 +0000939 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp16ToFp32WorkloadValidate,
940 reasonIfUnsupported,
941 input,
942 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100943}
944
945bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
946 const TensorInfo& output,
947 Optional<std::string&> reasonIfUnsupported) const
948{
Matthew Bentham34336f92023-04-27 12:13:50 +0000949 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp32ToFp16WorkloadValidate,
950 reasonIfUnsupported,
951 input,
952 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100953}
954
955bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
956 const TensorInfo& output,
957 const Convolution2dDescriptor& descriptor,
958 const TensorInfo& weights,
959 const Optional<TensorInfo>& biases,
960 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000961{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100962 bool isFastMathEnabled = false;
963#if defined(ARMCOMPUTENEON_ENABLED)
964 if (m_ModelContextPtr)
965 {
966 if (m_ModelContextPtr.get() != nullptr)
967 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100968 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100969 if (modelOptions)
970 {
971 isFastMathEnabled = modelOptions->IsFastMathEnabled();
972 }
973 }
974 }
975#endif
976
surmeh013537c2c2018-05-18 16:31:43 +0100977 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
978 reasonIfUnsupported,
979 input,
980 output,
981 descriptor,
982 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100983 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000984 isFastMathEnabled,
985 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000986}
987
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100988bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
989 const TensorInfo& output,
990 const Convolution3dDescriptor& descriptor,
991 const TensorInfo& weights,
992 const Optional<TensorInfo>& biases,
993 Optional<std::string&> reasonIfUnsupported) const
994{
995 bool isFastMathEnabled = false;
996#if defined(ARMCOMPUTENEON_ENABLED)
997 if (m_ModelContextPtr)
998 {
999 if (m_ModelContextPtr.get() != nullptr)
1000 {
1001 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
1002 if (modelOptions)
1003 {
1004 isFastMathEnabled = modelOptions->IsFastMathEnabled();
1005 }
1006 }
1007 }
1008#endif
1009
1010 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
1011 reasonIfUnsupported,
1012 input,
1013 output,
1014 descriptor,
1015 weights,
1016 biases,
1017 isFastMathEnabled,
1018 nullptr);
1019}
1020
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +01001021bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
1022 const TensorInfo& output,
1023 const DepthToSpaceDescriptor& descriptor,
1024 Optional<std::string&> reasonIfUnsupported) const
1025{
1026 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
1027 reasonIfUnsupported,
1028 input,
1029 output,
1030 descriptor);
1031}
1032
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001033bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
1034 const TensorInfo& output,
1035 const DepthwiseConvolution2dDescriptor& descriptor,
1036 const TensorInfo& weights,
1037 const Optional<TensorInfo>& biases,
1038 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001039{
telsoa01c577f2c2018-08-31 09:22:23 +01001040 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1041 reasonIfUnsupported,
1042 input,
1043 output,
1044 descriptor,
1045 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001046 biases,
1047 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001048}
1049
Narumol Prangnawarat01961a72019-05-30 16:47:12 +01001050bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
1051 const TensorInfo& output,
1052 Optional<std::string&> reasonIfUnsupported) const
1053{
1054 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
1055 reasonIfUnsupported,
1056 input,
1057 output);
1058}
1059
Pablo Tellof0bd6832019-04-26 17:58:13 +01001060bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
1061 const TensorInfo& output,
1062 const DepthwiseConvolution2dDescriptor& descriptor,
1063 const TensorInfo& weights,
1064 const Optional<TensorInfo>& biases,
1065 Optional<std::string&> reasonIfUnsupported) const
1066{
1067 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1068 reasonIfUnsupported,
1069 input,
1070 output,
1071 descriptor,
1072 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001073 biases,
1074 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +01001075}
1076
josh minor4a3c6102020-01-06 16:40:46 -06001077bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
1078 const TensorInfo& output,
1079 const ElementwiseUnaryDescriptor& descriptor,
1080 Optional<std::string&> reasonIfUnsupported) const
1081{
Derek Lambertic77874a2020-04-28 13:34:56 +01001082 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -06001083 {
Derek Lambertic77874a2020-04-28 13:34:56 +01001084 case UnaryOperation::Abs:
1085 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
1086 reasonIfUnsupported,
1087 input,
1088 output);
1089 case UnaryOperation::Exp:
1090 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
1091 reasonIfUnsupported,
1092 input,
1093 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +01001094 case UnaryOperation::LogicalNot:
1095 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
1096 reasonIfUnsupported,
1097 input,
1098 output);
1099 case UnaryOperation::Log:
1100 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
1101 reasonIfUnsupported,
1102 input,
1103 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001104 case UnaryOperation::Neg:
1105 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
1106 reasonIfUnsupported,
1107 input,
1108 output);
1109 case UnaryOperation::Rsqrt:
1110 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
1111 reasonIfUnsupported,
1112 input,
1113 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +00001114 case UnaryOperation::Sin:
1115 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
1116 reasonIfUnsupported,
1117 input,
1118 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +01001119 case UnaryOperation::Sqrt:
1120 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
1121 reasonIfUnsupported,
1122 input,
1123 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001124 default:
1125 return false;
josh minor4a3c6102020-01-06 16:40:46 -06001126 }
josh minor4a3c6102020-01-06 16:40:46 -06001127}
1128
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001129bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
1130 const TensorInfo& output,
1131 const FillDescriptor& descriptor,
1132 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +01001133{
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001134 armnn::IgnoreUnused(input);
1135 armnn::IgnoreUnused(output);
1136 armnn::IgnoreUnused(descriptor);
1137
1138 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +01001139}
1140
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001141bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
1142 const TensorInfo& output,
1143 Optional<std::string&> reasonIfUnsupported) const
1144{
Jan Eilers8eb25602020-03-09 12:13:48 +00001145 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001146 return IsNeonBackendSupported(reasonIfUnsupported) &&
1147 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1148 input.GetDataType(),
1149 &FalseFuncF16<>,
1150 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001151 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001152 &FalseFuncI32<>,
1153 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001154}
1155
1156bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1157 const TensorInfo& output,
1158 const TensorInfo& weights,
1159 const TensorInfo& biases,
1160 const FullyConnectedDescriptor& descriptor,
1161 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001162{
telsoa01c577f2c2018-08-31 09:22:23 +01001163 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1164 reasonIfUnsupported,
1165 input,
1166 output,
1167 weights,
1168 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001169 descriptor,
1170 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001171}
1172
Teresa Charlin9145e382023-08-17 18:44:58 +01001173bool NeonLayerSupport::IsFusedSupported(const std::vector<std::reference_wrapper<TensorInfo>>& inputs,
1174 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1175 const FusedDescriptor& descriptor,
1176 Optional<std::string&> reasonIfUnsupported) const
1177{
1178 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFusedWorkloadValidate,
1179 reasonIfUnsupported,
1180 inputs,
1181 outputs,
1182 descriptor,
1183 nullptr);
1184}
1185
Teresa Charlinf540eb82020-04-10 19:24:55 +01001186bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1187 const TensorInfo& input1,
1188 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001189 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001190 Optional<std::string&> reasonIfUnsupported) const
1191{
1192 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1193 reasonIfUnsupported,
1194 input0,
1195 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001196 output,
1197 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001198}
1199
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001200bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1201 const TensorInfo& input1,
1202 const TensorInfo& output,
1203 Optional<std::string&> reasonIfUnsupported) const
1204{
1205 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1206 reasonIfUnsupported,
1207 input0,
1208 input1,
1209 output);
1210}
1211
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001212bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1213 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001214{
Derek Lamberti901ea112019-12-10 22:07:09 +00001215 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001216}
1217
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001218bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1219 const TensorInfo& output,
1220 const InstanceNormalizationDescriptor& descriptor,
1221 Optional<std::string&> reasonIfUnsupported) const
1222{
1223 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1224 reasonIfUnsupported,
1225 input,
1226 output,
1227 descriptor);
1228}
1229
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001230bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1231 const TensorInfo& output,
1232 const L2NormalizationDescriptor& descriptor,
1233 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001234{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001235 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001236}
1237
James Conroy177df1e2020-11-13 10:18:51 +00001238bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1239 const TensorInfo& input1,
1240 const TensorInfo& output,
1241 const LogicalBinaryDescriptor& descriptor,
1242 Optional<std::string&> reasonIfUnsupported) const
1243{
1244 switch(descriptor.m_Operation)
1245 {
1246 case LogicalBinaryOperation::LogicalAnd:
1247 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1248 reasonIfUnsupported,
1249 input0,
1250 input1,
1251 output);
1252 case LogicalBinaryOperation::LogicalOr:
1253 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1254 reasonIfUnsupported,
1255 input0,
1256 input1,
1257 output);
1258 default:
1259 return false;
1260 }
1261}
1262
Keith Davis69e653f2020-07-02 11:49:26 +01001263bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1264 const TensorInfo& output,
1265 const LogSoftmaxDescriptor& descriptor,
1266 Optional<std::string&> reasonIfUnsupported) const
1267{
1268 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1269}
1270
Jan Eilersad5293a2019-07-08 09:57:55 +01001271bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1272 const TensorInfo& outputStateIn,
1273 const TensorInfo& cellStateIn,
1274 const TensorInfo& scratchBuffer,
1275 const TensorInfo& outputStateOut,
1276 const TensorInfo& cellStateOut,
1277 const TensorInfo& output,
1278 const LstmDescriptor& descriptor,
1279 const LstmInputParamsInfo& paramsInfo,
1280 Optional<std::string&> reasonIfUnsupported) const
1281{
1282 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1283 reasonIfUnsupported,
1284 input,
1285 outputStateIn,
1286 cellStateIn,
1287 scratchBuffer,
1288 outputStateOut,
1289 cellStateOut,
1290 output,
1291 descriptor,
1292 paramsInfo);
1293}
1294
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001295bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1296 const TensorInfo& input1,
1297 const TensorInfo& output,
1298 Optional<std::string&> reasonIfUnsupported) const
1299{
1300 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1301 reasonIfUnsupported,
1302 input0,
1303 input1,
1304 output);
1305}
1306
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001307bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1308 const TensorInfo& output,
1309 const MeanDescriptor& descriptor,
1310 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001311{
Matthew Benthamfd899962018-12-31 15:49:42 +00001312 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1313 reasonIfUnsupported,
1314 input,
1315 output,
1316 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001317}
1318
Conor Kennedy54b21692019-01-09 07:57:38 +00001319bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1320 const TensorInfo& input1,
1321 const TensorInfo& output,
1322 Optional<std::string&> reasonIfUnsupported) const
1323{
1324 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1325 reasonIfUnsupported,
1326 input0,
1327 input1,
1328 output);
1329}
1330
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001331bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1332 const TensorInfo& input1,
1333 const TensorInfo& output,
1334 Optional<std::string&> reasonIfUnsupported) const
1335{
1336 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1337 reasonIfUnsupported,
1338 input0,
1339 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001340 output,
1341 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001342}
1343
Pablo Telloe61f0712020-01-23 10:37:17 +00001344bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1345 const TensorInfo& input1,
1346 const TensorInfo& output,
1347 Optional<std::string&> reasonIfUnsupported) const
1348{
1349 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1350 reasonIfUnsupported,
1351 input0,
1352 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001353 output,
1354 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001355}
1356
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001357bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1358 const TensorInfo& output,
1359 const NormalizationDescriptor& descriptor,
1360 Optional<std::string&> reasonIfUnsupported) const
1361{
1362 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1363 reasonIfUnsupported,
1364 input,
1365 output,
1366 descriptor);
1367}
1368
1369bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1370 Optional<std::string&> reasonIfUnsupported) const
1371{
Derek Lamberti901ea112019-12-10 22:07:09 +00001372 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001373}
1374
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001375bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1376 const TensorInfo& output,
1377 const PadDescriptor& descriptor,
1378 Optional<std::string&> reasonIfUnsupported) const
1379{
1380 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1381 reasonIfUnsupported,
1382 input,
1383 output,
1384 descriptor);
1385}
1386
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001387bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1388 const TensorInfo& output,
1389 const PermuteDescriptor& descriptor,
1390 Optional<std::string&> reasonIfUnsupported) const
1391{
1392 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001393}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001394
1395bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1396 const TensorInfo& output,
1397 const Pooling2dDescriptor& descriptor,
1398 Optional<std::string&> reasonIfUnsupported) const
1399{
1400 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1401}
1402
Ryan OShea19e79422022-05-04 00:38:03 +01001403bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1404 const TensorInfo& output,
1405 const Pooling3dDescriptor& descriptor,
1406 Optional<std::string&> reasonIfUnsupported) const
1407{
1408 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1409}
1410
Nikhil Raj9b461482019-07-03 15:58:31 +01001411bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1412 const armnn::TensorInfo &alpha,
1413 const armnn::TensorInfo &output,
1414 armnn::Optional<std::string &> reasonIfUnsupported) const
1415{
1416 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1417}
1418
James Conroycc340932020-05-12 18:08:52 +01001419bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1420 const TensorInfo& previousOutputIn,
1421 const TensorInfo& previousCellStateIn,
1422 const TensorInfo& outputStateOut,
1423 const TensorInfo& cellStateOut,
1424 const TensorInfo& output,
1425 const QLstmDescriptor& descriptor,
1426 const LstmInputParamsInfo& paramsInfo,
1427 Optional<std::string&> reasonIfUnsupported) const
1428{
1429 // Check required here in order to pass IsLayerSupported for datatypes tests
1430 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1431 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1432 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1433 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1434 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1435 output.GetDataType() == armnn::DataType::QAsymmS8)
1436 {
1437 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1438 reasonIfUnsupported,
1439 input,
1440 previousCellStateIn,
1441 previousOutputIn,
1442 cellStateOut,
1443 outputStateOut,
1444 output,
1445 descriptor,
1446 paramsInfo);
1447 }
1448 else
1449 {
1450 return false;
1451 }
1452}
1453
Sadik Armaganfabc2892019-05-31 09:05:11 +01001454bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1455 const TensorInfo& output,
1456 Optional<std::string&> reasonIfUnsupported) const
1457{
1458 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1459 reasonIfUnsupported,
1460 input,
1461 output);
1462}
1463
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001464bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1465 const TensorInfo& cellStateIn,
1466 const TensorInfo& outputStateIn,
1467 const TensorInfo& cellStateOut,
1468 const TensorInfo& outputStateOut,
1469 const QuantizedLstmInputParamsInfo& paramsInfo,
1470 Optional<std::string&> reasonIfUnsupported) const
1471{
1472 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1473 reasonIfUnsupported,
1474 input,
1475 cellStateIn,
1476 outputStateIn,
1477 cellStateOut,
1478 outputStateOut,
1479 paramsInfo);
1480}
1481
Sadik Armagana2747482021-02-09 10:28:54 +00001482bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1483 const TensorInfo& output,
1484 const ReduceDescriptor& descriptor,
1485 Optional<std::string&> reasonIfUnsupported) const
1486{
1487 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1488 reasonIfUnsupported,
1489 input,
1490 output,
1491 descriptor);
1492}
1493
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001494bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001495 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001496 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001497 Optional<std::string&> reasonIfUnsupported) const
1498{
Jan Eilers8eb25602020-03-09 12:13:48 +00001499 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001500 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1501 reasonIfUnsupported,
1502 input,
1503 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001504}
1505
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001506bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1507 const TensorInfo& output,
1508 const ResizeDescriptor& descriptor,
1509 Optional<std::string&> reasonIfUnsupported) const
1510{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001511 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1512 reasonIfUnsupported,
1513 input,
1514 output,
1515 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001516}
1517
josh minor036f02d2019-11-15 14:53:22 -06001518bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1519 const TensorInfo& output,
1520 const SliceDescriptor& descriptor,
1521 Optional<std::string&> reasonIfUnsupported) const
1522{
1523 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1524 reasonIfUnsupported,
1525 input,
1526 output,
1527 descriptor);
1528}
1529
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001530bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1531 const TensorInfo& output,
1532 const SoftmaxDescriptor& descriptor,
1533 Optional<std::string&> reasonIfUnsupported) const
1534{
1535 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1536}
1537
Mike Kelly0be3a882020-01-24 11:27:50 +00001538bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1539 const TensorInfo& output,
1540 const SpaceToBatchNdDescriptor& descriptor,
1541 Optional<std::string&> reasonIfUnsupported) const
1542{
1543 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1544 reasonIfUnsupported,
1545 input,
1546 output,
1547 descriptor);
1548}
1549
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001550bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001551 const TensorInfo& output,
1552 const SpaceToDepthDescriptor& descriptor,
1553 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001554{
1555 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1556 reasonIfUnsupported,
1557 input,
1558 output,
1559 descriptor);
1560}
1561
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001562bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001563 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1564 const ViewsDescriptor& descriptor,
1565 Optional<std::string&> reasonIfUnsupported) const
1566{
1567#if defined(ARMCOMPUTENEON_ENABLED)
1568 // Split along the last dimension, cannot use sub-tensors
1569 // as width and height of the sub-tensors do not match
1570 // the width and height of the parent tensor
1571 // in case of input with more than 2D.
1572 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1573 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1574 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1575 {
1576 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1577 reasonIfUnsupported,
1578 input,
1579 outputs,
1580 *splitAxis.begin());
1581 }
1582#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001583 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001584 for (auto output : outputs)
1585 {
1586 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1587 {
1588 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1589 return false;
1590 }
1591 }
1592 return true;
1593}
1594
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001595bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1596 const TensorInfo& output,
1597 const StackDescriptor& descriptor,
1598 Optional<std::string&> reasonIfUnsupported) const
1599{
1600 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1601 reasonIfUnsupported,
1602 inputs,
1603 output,
1604 descriptor);
1605}
1606
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001607bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1608 const TensorInfo& output,
1609 const StridedSliceDescriptor& descriptor,
1610 Optional<std::string&> reasonIfUnsupported) const
1611{
1612 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1613 reasonIfUnsupported,
1614 input,
1615 output,
1616 descriptor);
1617}
1618
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001619bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1620 const TensorInfo& input1,
1621 const TensorInfo& output,
1622 Optional<std::string&> reasonIfUnsupported) const
1623{
1624 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1625 reasonIfUnsupported,
1626 input0,
1627 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001628 output,
1629 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001630}
1631
David Monahan36e6eae2023-07-26 18:37:45 +01001632bool NeonLayerSupport::IsTileSupported(const TensorInfo& input,
1633 const TensorInfo& output,
1634 const TileDescriptor& descriptor,
1635 Optional<std::string&> reasonIfUnsupported) const
1636{
1637 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTileWorkloadValidate,
1638 reasonIfUnsupported,
1639 input,
1640 output,
1641 descriptor);
1642}
1643
Sadik Armagan581742d2019-08-12 14:11:37 +01001644bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1645 const TensorInfo& output,
1646 const TransposeConvolution2dDescriptor& descriptor,
1647 const TensorInfo& weights,
1648 const Optional<TensorInfo>& biases,
1649 Optional<std::string&> reasonIfUnsupported) const
1650{
1651 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1652 reasonIfUnsupported,
1653 input,
1654 output,
1655 descriptor,
1656 weights,
1657 biases);
1658}
1659
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001660bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1661 const TensorInfo& output,
1662 const TransposeDescriptor& descriptor,
1663 Optional<std::string&> reasonIfUnsupported) const
1664{
1665 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1666}
1667
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001668bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1669 const TensorInfo& outputStateIn,
1670 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001671 const TensorInfo& outputStateOut,
1672 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001673 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001674 const UnidirectionalSequenceLstmDescriptor& descriptor,
1675 const LstmInputParamsInfo& paramsInfo,
1676 Optional<std::string&> reasonIfUnsupported) const
1677{
Mike Kelly12994962022-04-21 11:57:09 +01001678 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1679 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1680 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1681 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1682 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1683 output.GetDataType() == armnn::DataType::QAsymmS8)
1684 {
1685 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1686 reasonIfUnsupported,
1687 input,
1688 outputStateIn,
1689 cellStateIn,
1690 outputStateOut,
1691 cellStateOut,
1692 output,
1693 descriptor,
1694 paramsInfo);
1695 }
1696 else
1697 {
1698 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1699 reasonIfUnsupported,
1700 input,
1701 outputStateIn,
1702 cellStateIn,
1703 outputStateOut,
1704 cellStateOut,
1705 output,
1706 descriptor,
1707 paramsInfo);
1708 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001709}
1710
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001711} // namespace armnn