blob: 672b2f377f79ed70884c5fb32467cfa7bc183de3 [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"
David Beck3e9e1152018-10-17 14:17:50 +01007#include "NeonBackendId.hpp"
Sadik Armagan045f6be2020-09-10 13:37:32 +01008#include "NeonBackendModelContext.hpp"
telsoa014fcda012018-03-09 14:13:49 +00009
Derek Lambertic77874a2020-04-28 13:34:56 +010010#include <armnn/Exceptions.hpp>
telsoa014fcda012018-03-09 14:13:49 +000011#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010012#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000013#include <armnn/BackendRegistry.hpp>
telsoa014fcda012018-03-09 14:13:49 +000014
Matteo Martincighc601aa62019-10-29 15:03:22 +000015#include <InternalTypes.hpp>
16#include <LayerSupportCommon.hpp>
Jan Eilers8eb25602020-03-09 12:13:48 +000017#include <armnn/utility/IgnoreUnused.hpp>
Sadik Armagan045f6be2020-09-10 13:37:32 +010018#include <armnn/utility/PolymorphicDowncast.hpp>
telsoa014fcda012018-03-09 14:13:49 +000019
Matteo Martincighd95e9062019-01-31 15:35:59 +000020#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010021#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar710f6642019-11-27 14:48:32 +000022#include <aclCommon/ArmComputeTensorUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010023#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000024#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010025#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010026#include "workloads/NeonArgMinMaxWorkload.hpp"
Teresa Charlin0f86ecf2022-10-13 15:47:08 +010027#include "workloads/NeonBatchMatMulWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000028#include "workloads/NeonBatchNormalizationWorkload.hpp"
Mike Kelly56858022020-01-27 12:14:47 +000029#include "workloads/NeonBatchToSpaceNdWorkload.hpp"
Sadik Armagan48f011e2021-04-21 10:50:34 +010030#include "workloads/NeonCastWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010031#include "workloads/NeonChannelShuffleWorkload.hpp"
Teresa Charlincedd34f2020-03-30 11:17:30 +010032#include "workloads/NeonComparisonWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010033#include "workloads/NeonConcatWorkload.hpp"
Mike Kelly0886ac42020-04-27 09:55:40 +010034#include "workloads/NeonConstantWorkload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010035#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010036#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010037#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010038#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010039#include "workloads/NeonDequantizeWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010040#include "workloads/NeonExpWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010041#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010042#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010043#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010044#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000045#include "workloads/NeonLogicalAndWorkload.hpp"
46#include "workloads/NeonLogicalNotWorkload.hpp"
47#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010048#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000049#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000050#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000051#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000052#include "workloads/NeonMultiplicationWorkload.hpp"
Pablo Telloe61f0712020-01-23 10:37:17 +000053#include "workloads/NeonDivisionWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000054#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010055#include "workloads/NeonNormalizationFloatWorkload.hpp"
56#include "workloads/NeonFullyConnectedWorkload.hpp"
Teresa Charlinf540eb82020-04-10 19:24:55 +010057#include "workloads/NeonGatherWorkload.hpp"
Teresa Charlinbd22c7d2022-04-26 18:14:12 +010058#include "workloads/NeonGatherNdWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000059#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010060#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010061#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010062#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010063#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010064#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010065#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010066#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000067#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000068#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010069#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010070#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010071#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060072#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010073#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000074#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010075#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010076#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010077#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010078#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010079#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000080#include "workloads/NeonSubtractionWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010081#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
Mike Kellyc9ea45a2020-02-28 18:11:58 +000082#include "workloads/NeonTransposeWorkload.hpp"
Cathal Corbettfd5bec42022-03-03 15:13:23 +000083#include "workloads/NeonUnidirectionalSequenceLstmFloatWorkload.hpp"
Mike Kelly12994962022-04-21 11:57:09 +010084#include "workloads/NeonUnidirectionalSequenceLstmWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000085#endif
86
telsoa014fcda012018-03-09 14:13:49 +000087namespace armnn
88{
telsoa014fcda012018-03-09 14:13:49 +000089
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010090namespace
arovir017ff76c52018-10-09 09:40:58 +010091{
telsoa014fcda012018-03-09 14:13:49 +000092
Cathal Corbett80f71a82022-12-20 18:25:40 +000093const TensorInfo OverrideDataType(const TensorInfo& info, Optional<DataType> type)
94{
95 if (!type)
96 {
97 return info;
98 }
99 return TensorInfo(info.GetShape(),
100 type.value(),
101 info.GetQuantizationScale(),
102 info.GetQuantizationOffset(),
103 info.IsConstant());
104}
105
Derek Lamberti901ea112019-12-10 22:07:09 +0000106template< typename ... Args>
107bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
telsoa014fcda012018-03-09 14:13:49 +0000108{
Jan Eilers8eb25602020-03-09 12:13:48 +0000109 IgnoreUnused(reasonIfUnsupported, (args)...);
Matteo Martincighd95e9062019-01-31 15:35:59 +0000110#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000111 return true;
112#else
Derek Lamberti0790dce2019-04-15 18:37:35 +0100113 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +0000114 return false;
115#endif
116}
117
telsoa01c577f2c2018-08-31 09:22:23 +0100118template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +0100119bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +0000120 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +0100121 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000122 Uint8Func uint8FuncPtr,
123 Params&&... params)
124{
125 return IsNeonBackendSupported(reasonIfUnsupported) &&
126 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
127 dataType,
128 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +0100129 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000130 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +0000131 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000132 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +0000133 std::forward<Params>(params)...);
134}
135
Matteo Martincighd95e9062019-01-31 15:35:59 +0000136#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +0000137template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +0100138inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +0000139{
140 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
141 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
142 if (!supported && reasonIfUnsupported)
143 {
arovir01085f0a42018-10-08 14:48:19 +0100144 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000145 }
146 return supported;
147}
148
149#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
150 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
151#else
152#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
Derek Lamberti901ea112019-12-10 22:07:09 +0000153 return IsNeonBackendSupported(reasonIfUnsupported, __VA_ARGS__);
telsoa014fcda012018-03-09 14:13:49 +0000154#endif
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100155} // anonymous namespace
156
Sadik Armagan045f6be2020-09-10 13:37:32 +0100157NeonLayerSupport::NeonLayerSupport(const IBackendInternal::IBackendSpecificModelContextPtr& modelContextPtr)
158 : m_ModelContextPtr(modelContextPtr)
159{
160}
161
162NeonLayerSupport::NeonLayerSupport()
163 : m_ModelContextPtr(nullptr)
164{
165}
166
Cathal Corbett80f71a82022-12-20 18:25:40 +0000167bool IsLayerTypeSupported(const LayerType& type,
168 const std::vector<TensorInfo>& infos,
169 const BaseDescriptor& descriptor,
170 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
171 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
172 Optional<std::string&> reasonIfUnsupported,
173 const NeonLayerSupport& support)
Cathal Corbett34b429c2021-12-24 12:24:40 +0000174{
175 switch (type)
176 {
177 case LayerType::Activation:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000178 return support.IsActivationSupported(infos[0],
179 infos[1],
180 *(PolymorphicDowncast<const ActivationDescriptor*>(&descriptor)),
181 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000182 case LayerType::Addition:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000183 return support.IsAdditionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000184 case LayerType::ArgMinMax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000185 return support.IsArgMinMaxSupported(infos[0],
186 infos[1],
187 *(PolymorphicDowncast<const ArgMinMaxDescriptor*>(&descriptor)),
188 reasonIfUnsupported);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100189 case LayerType::BatchMatMul:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000190 return support.IsBatchMatMulSupported(infos[0],
191 infos[1],
192 infos[2],
193 *(PolymorphicDowncast<const BatchMatMulDescriptor*>(&descriptor)),
194 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000195 case LayerType::BatchNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000196 return support.IsBatchNormalizationSupported(infos[0],
197 infos[1],
198 infos[2],
199 infos[3],
200 infos[4],
201 infos[5],
202 *(PolymorphicDowncast<const
203 BatchNormalizationDescriptor*>(&descriptor)),
204 reasonIfUnsupported);
205 case LayerType::BatchToSpaceNd:
206 return support.IsBatchToSpaceNdSupported(infos[0],
207 infos[1],
208 *(PolymorphicDowncast<const
209 BatchToSpaceNdDescriptor*>(&descriptor)),
210 reasonIfUnsupported);
211 case LayerType::Cast:
212 return support.IsCastSupported(infos[0], infos[1], reasonIfUnsupported);
213 case LayerType::ChannelShuffle:
214 return support.IsChannelShuffleSupported(infos[0],
215 infos[1],
216 *(PolymorphicDowncast<const
217 ChannelShuffleDescriptor*>(&descriptor)),
218 reasonIfUnsupported);
219 case LayerType::Comparison:
220 return support.IsComparisonSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000221 infos[1],
222 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000223 *(PolymorphicDowncast<const ComparisonDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000224 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000225 case LayerType::Concat:
226 {
227 std::vector<const TensorInfo*> inputInfos;
228 for (uint32_t i = 0; i < (infos.size() - 1); i++)
229 {
230 inputInfos.push_back(&infos[i]);
231 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000232 return support.IsConcatSupported(inputInfos,
233 infos[infos.size() - 1],
234 *(PolymorphicDowncast<const OriginsDescriptor*>(&descriptor)),
235 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000236 }
237 case LayerType::Constant:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000238 return support.IsConstantSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000239 case LayerType::ConvertFp16ToFp32:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000240 return support.IsConvertFp16ToFp32Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000241 case LayerType::ConvertFp32ToFp16:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000242 return support.IsConvertFp32ToFp16Supported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000243 case LayerType::Convolution2d:
244 {
245 if (infos.size() != 4)
246 {
247 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
248 "TensorInfos should be of format: {input, output, weights, biases}.");
249 }
250
251 auto desc = *(PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor));
252 if (infos[3] == TensorInfo())
253 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000254 return support.IsConvolution2dSupported(infos[0],
255 infos[1],
256 desc,
257 infos[2],
258 EmptyOptional(),
259 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000260 }
261 else
262 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000263 return support.IsConvolution2dSupported(infos[0],
264 infos[1],
265 desc,
266 infos[2],
267 infos[3],
268 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000269 }
270 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000271 case LayerType::Convolution3d:
272 {
273 if (infos.size() != 4)
274 {
275 throw InvalidArgumentException("Invalid number of Convolution3d TensorInfos. "
276 "TensorInfos should be of format: {input, output, weights, biases}.");
277 }
278
279 auto desc = *(PolymorphicDowncast<const Convolution3dDescriptor*>(&descriptor));
280 if (infos[3] == TensorInfo())
281 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000282 return support.IsConvolution3dSupported(infos[0],
283 infos[1],
284 desc,
285 infos[2],
286 EmptyOptional(),
287 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000288 }
289 else
290 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000291 return support.IsConvolution3dSupported(infos[0],
292 infos[1],
293 desc,
294 infos[2],
295 infos[3],
296 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000297 }
298 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000299 case LayerType::DepthToSpace:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000300 return support.IsDepthToSpaceSupported(infos[0],
301 infos[1],
302 *(PolymorphicDowncast<const DepthToSpaceDescriptor*>(&descriptor)),
303 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000304 case LayerType::DepthwiseConvolution2d:
305 {
306 if (infos.size() != 4)
307 {
308 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2d TensorInfos. "
309 "TensorInfos should be of format: {input, output, weights, biases}.");
310 }
311
312 auto desc = *(PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor));
313 if (infos[3] == TensorInfo())
314 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000315 return support.IsDepthwiseConvolutionSupported(infos[0],
316 infos[1],
317 desc,
318 infos[2],
319 EmptyOptional(),
320 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000321 }
322 else
323 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000324 return support.IsDepthwiseConvolutionSupported(infos[0],
325 infos[1],
326 desc,
327 infos[2],
328 infos[3],
329 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000330 }
331 }
332 case LayerType::Dequantize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000333 return support.IsDequantizeSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000334 case LayerType::DetectionPostProcess:
335 {
336 auto desc = *(PolymorphicDowncast<const DetectionPostProcessDescriptor*>(&descriptor));
Cathal Corbett80f71a82022-12-20 18:25:40 +0000337 return support.IsDetectionPostProcessSupported(infos[0],
338 infos[1],
339 infos[2],
340 infos[3],
341 infos[4],
342 infos[5],
343 infos[6],
344 desc,
345 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000346 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000347 case LayerType::Division:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000348 return support.IsDivisionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Mike Kelly3ec30772023-03-08 13:47:17 +0000349 case LayerType::ElementwiseBinary:
350 {
351 auto desc = *(PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor));
352
353 switch (desc.m_Operation)
354 {
355 case BinaryOperation::Add:
356 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
357 reasonIfUnsupported,
358 infos[0],
359 infos[1],
360 infos[2],
361 nullptr);
362 case BinaryOperation::Div:
363 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
364 reasonIfUnsupported,
365 infos[0],
366 infos[1],
367 infos[2],
368 nullptr);
369 case BinaryOperation::Maximum:
370 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
371 reasonIfUnsupported,
372 infos[0],
373 infos[1],
374 infos[2]);
375 case BinaryOperation::Minimum:
376 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
377 reasonIfUnsupported,
378 infos[0],
379 infos[1],
380 infos[2]);
381 case BinaryOperation::Mul:
382 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
383 reasonIfUnsupported,
384 infos[0],
385 infos[1],
386 infos[2],
387 nullptr);
388 case BinaryOperation::Sub:
389 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
390 reasonIfUnsupported,
391 infos[0],
392 infos[1],
393 infos[2],
394 nullptr);
395 default:
396 return false;
397 }
398 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000399 case LayerType::ElementwiseUnary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000400 return support.IsElementwiseUnarySupported(infos[0],
401 infos[1],
402 *(PolymorphicDowncast<const
403 ElementwiseUnaryDescriptor*>(&descriptor)),
404 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000405 case LayerType::Fill:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000406 return support.IsFillSupported(infos[0],
407 infos[1],
408 *(PolymorphicDowncast<const FillDescriptor*>(&descriptor)),
409 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000410 case LayerType::Floor:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000411 return support.IsFloorSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000412 case LayerType::FullyConnected:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000413 return support.IsFullyConnectedSupported(infos[0],
414 infos[1],
415 infos[2],
416 infos[3],
417 *(PolymorphicDowncast<const
418 FullyConnectedDescriptor*>(&descriptor)),
419 reasonIfUnsupported);
420 case LayerType::Gather:
421 return support.IsGatherSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000422 infos[1],
423 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000424 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000425 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100426 case LayerType::GatherNd:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000427 return support.IsGatherNdSupported(infos[0],
428 infos[1],
429 infos[2],
430 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000431 case LayerType::Input:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000432 return support.IsInputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000433 case LayerType::InstanceNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000434 return support.IsInstanceNormalizationSupported(infos[0],
435 infos[1],
436 *(PolymorphicDowncast<const
437 InstanceNormalizationDescriptor*>(&descriptor)),
438 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000439 case LayerType::L2Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000440 return support.IsL2NormalizationSupported(infos[0],
441 infos[1],
442 *(PolymorphicDowncast<const
443 L2NormalizationDescriptor*>(&descriptor)),
444 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000445 case LayerType::LogicalBinary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000446 return support.IsLogicalBinarySupported(infos[0],
447 infos[1],
448 infos[2],
449 *(PolymorphicDowncast<const
450 LogicalBinaryDescriptor*>(&descriptor)),
451 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000452 case LayerType::LogSoftmax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000453 return support.IsLogSoftmaxSupported(infos[0],
454 infos[1],
455 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
456 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000457 case LayerType::Lstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000458 return support.IsLstmSupported(infos[0],
459 infos[1],
460 infos[2],
461 infos[3],
462 infos[4],
463 infos[5],
464 infos[6],
465 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
466 lstmParamsInfo.value(),
467 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000468 case LayerType::Map:
469 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000470 case LayerType::Maximum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000471 return support.IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000472 case LayerType::Mean:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000473 return support.IsMeanSupported(infos[0],
474 infos[1],
475 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
476 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000477 case LayerType::MemCopy:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000478 return support.IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000479 case LayerType::MemImport:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000480 return support.IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000481 case LayerType::Merge:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000482 return support.IsMergeSupported(infos[0],
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000483 infos[1],
484 infos[2],
485 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000486 case LayerType::Minimum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000487 return support.IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000488 case LayerType::Multiplication:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000489 return support.IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000490 case LayerType::Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000491 return support.IsNormalizationSupported(infos[0],
492 infos[1],
493 *(PolymorphicDowncast<const
494 NormalizationDescriptor*>(&descriptor)),
495 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000496 case LayerType::Output:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000497 return support.IsOutputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000498 case LayerType::Pad:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000499 return support.IsPadSupported(infos[0],
500 infos[1],
501 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
502 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000503 case LayerType::Permute:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000504 return support.IsPermuteSupported(infos[0],
505 infos[1],
506 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
507 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000508 case LayerType::Pooling2d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000509 return support.IsPooling2dSupported(infos[0],
510 infos[1],
511 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
512 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100513 case LayerType::Pooling3d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000514 return support.IsPooling3dSupported(infos[0],
515 infos[1],
516 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
517 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000518 case LayerType::Prelu:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000519 return support.IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000520 case LayerType::QLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000521 return support.IsQLstmSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000522 infos[1],
523 infos[2],
524 infos[3],
525 infos[4],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000526 infos[5],
527 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
528 lstmParamsInfo.value(),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000529 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000530 case LayerType::Quantize:
531 return support.IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
532 case LayerType::QuantizedLstm:
533 return support.IsQuantizedLstmSupported(infos[0],
534 infos[1],
535 infos[2],
536 infos[3],
537 infos[4],
538 quantizedLstmParamsInfo.value(),
539 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000540 case LayerType::Rank:
541 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000542 case LayerType::Reshape:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000543 return support.IsReshapeSupported(infos[0],
544 infos[1],
545 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
546 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000547 case LayerType::Resize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000548 return support.IsResizeSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000549 infos[1],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000550 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000551 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000552 case LayerType::Reduce:
553 return support.IsReduceSupported(infos[0],
554 infos[1],
555 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
556 reasonIfUnsupported);
557 case LayerType::Shape:
558 return support.IsShapeSupported(infos[0],
559 infos[1],
560 reasonIfUnsupported);
561 case LayerType::Slice:
562 return support.IsSliceSupported(infos[0],
563 infos[1],
564 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
565 reasonIfUnsupported);
566 case LayerType::Softmax:
567 return support.IsSoftmaxSupported(infos[0],
568 infos[1],
569 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
570 reasonIfUnsupported);
571 case LayerType::SpaceToBatchNd:
572 return support.IsSpaceToBatchNdSupported(infos[0],
573 infos[1],
574 *(PolymorphicDowncast<const
575 SpaceToBatchNdDescriptor*>(&descriptor)),
576 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000577 case LayerType::SpaceToDepth:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000578 return support.IsSpaceToDepthSupported(infos[0],
579 infos[1],
580 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
581 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000582 case LayerType::Splitter:
583 {
584 std::vector<TensorInfo> outputInfos;
585 for (uint32_t i = 1; i < infos.size(); i++)
586 {
587 outputInfos.push_back(infos[i]);
588 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000589 return support.IsSplitterSupported(infos[0],
590 {outputInfos.begin(), outputInfos.end()},
591 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
592 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000593 }
594 case LayerType::Stack:
595 {
596 std::vector<const TensorInfo*> inputInfos;
597 for (uint32_t i = 0; i < infos.size() - 1; i++)
598 {
599 inputInfos.push_back(&infos[i]);
600 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000601 return support.IsStackSupported(inputInfos,
602 infos[infos.size() - 1],
603 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
604 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000605 }
606 case LayerType::StridedSlice:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000607 return support.IsStridedSliceSupported(infos[0],
608 infos[1],
609 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
610 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000611 case LayerType::Subtraction:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000612 return support.IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000613 case LayerType::Transpose:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000614 return support.IsTransposeSupported(infos[0],
615 infos[1],
616 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
617 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000618 case LayerType::TransposeConvolution2d:
619 {
620 if (infos.size() != 4)
621 {
622 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
623 "TensorInfos should be of format: {input, output, weights, biases}.");
624 }
625
626 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
627 if (infos[3] == TensorInfo())
628 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000629 return support.IsTransposeConvolution2dSupported(infos[0],
630 infos[1],
631 desc,
632 infos[2],
633 EmptyOptional(),
634 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000635 }
636 else
637 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000638 return support.IsTransposeConvolution2dSupported(infos[0],
639 infos[1],
640 desc,
641 infos[2],
642 infos[3],
643 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000644 }
645 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000646 case LayerType::UnidirectionalSequenceLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000647 {
648 auto desc = *(PolymorphicDowncast<const UnidirectionalSequenceLstmDescriptor*>(&descriptor));
649 return support.IsUnidirectionalSequenceLstmSupported(infos[0],
650 infos[1],
651 infos[2],
652 infos[3],
653 infos[4],
654 infos[5],
655 desc,
656 lstmParamsInfo.value(),
657 reasonIfUnsupported);
658 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000659 case LayerType::Unmap:
660 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000661 default:
662 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000663 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100664 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000665 return false;
666 }
667}
668
Cathal Corbett80f71a82022-12-20 18:25:40 +0000669bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
670 const std::vector<TensorInfo>& infos,
671 const BaseDescriptor& descriptor,
672 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
673 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
674 Optional<std::string&> reasonIfUnsupported) const
675{
676 bool isSupported = IsLayerTypeSupported(type,
677 infos,
678 descriptor,
679 lstmParamsInfo,
680 quantizedLstmParamsInfo,
681 reasonIfUnsupported,
682 *this);
683
684 // For android-nn-driver and support library, to run FP16 operations on CpuAcc we need at least v8.2
685 // architecture. If the available architecture is older than v8.2, we can check if the operator is
686 // supported by changing operator inputs & outputs to be FP32.
687 // This does not change the operator datatype in the above parsers to be FP32. We are simply reporting
688 // to the parsers if the operator can supported in ArmNN. We will then re-enter ArmNN (Network.cpp)
689 // where we will recheck IsLayerSupported() on the FP16 datatype, update the operator to be FP32,
690 // and, insert convert layers around the FP32 operator.
691 if (reasonIfUnsupported.has_value())
692 {
693 std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
694 if (!isSupported
695 && reasonIfUnsupported.value().find(checkStr) != std::string::npos)
696 {
697 std::vector<TensorInfo> newInfos;
698 for (auto info: infos)
699 {
700 newInfos.emplace_back(OverrideDataType(info, DataType::Float32));
701 }
702
703 std::string tmpString;
704 return IsLayerTypeSupported(type,
705 newInfos,
706 descriptor,
707 lstmParamsInfo,
708 quantizedLstmParamsInfo,
709 tmpString,
710 *this);
711 }
712 }
713
714 return isSupported;
715}
716
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100717bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
718 const TensorInfo& output,
719 const ActivationDescriptor& descriptor,
720 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000721{
Jan Eilers8eb25602020-03-09 12:13:48 +0000722 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100723 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
724 reasonIfUnsupported,
725 input,
726 output,
727 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000728}
729
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100730bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
731 const TensorInfo& input1,
732 const TensorInfo& output,
733 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000734{
telsoa01c577f2c2018-08-31 09:22:23 +0100735 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
736 reasonIfUnsupported,
737 input0,
738 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000739 output,
740 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000741}
742
James Conroyd47a0642019-09-17 14:22:06 +0100743bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
744 const TensorInfo& output,
745 const ArgMinMaxDescriptor& descriptor,
746 Optional<std::string&> reasonIfUnsupported) const
747{
748 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
749 reasonIfUnsupported,
750 input,
751 output,
752 descriptor);
753}
754
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100755bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
756 const TensorInfo& inputY,
757 const TensorInfo& output,
758 const BatchMatMulDescriptor& descriptor,
759 Optional<std::string&> reasonIfUnsupported) const
760{
761 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
762 reasonIfUnsupported,
763 inputX,
764 inputY,
765 output,
766 descriptor);
767}
768
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100769bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
770 const TensorInfo& output,
771 const TensorInfo& mean,
772 const TensorInfo& var,
773 const TensorInfo& beta,
774 const TensorInfo& gamma,
775 const BatchNormalizationDescriptor& descriptor,
776 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000777{
telsoa01c577f2c2018-08-31 09:22:23 +0100778 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
779 reasonIfUnsupported,
780 input,
781 output,
782 mean,
783 var,
784 beta,
785 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000786 descriptor,
787 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000788}
789
Mike Kelly56858022020-01-27 12:14:47 +0000790bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
791 const TensorInfo& output,
792 const BatchToSpaceNdDescriptor& descriptor,
793 Optional<std::string&> reasonIfUnsupported) const
794{
795 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
796 reasonIfUnsupported,
797 input,
798 output,
799 descriptor);
800}
801
Sadik Armagan48f011e2021-04-21 10:50:34 +0100802bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
803 const TensorInfo& output,
804 Optional<std::string&> reasonIfUnsupported) const
805{
806 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
807 reasonIfUnsupported,
808 input,
809 output);
810}
811
Teresa Charline89dd692021-09-01 16:30:34 +0100812bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
813 const TensorInfo& output,
814 const ChannelShuffleDescriptor& descriptor,
815 Optional<std::string&> reasonIfUnsupported) const
816{
817 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
818 reasonIfUnsupported,
819 input,
820 output,
821 descriptor);
822}
823
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100824bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
825 const TensorInfo& input1,
826 const TensorInfo& output,
827 const ComparisonDescriptor& descriptor,
828 Optional<std::string&> reasonIfUnsupported) const
829{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100830
Teresa Charlincedd34f2020-03-30 11:17:30 +0100831 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
832 reasonIfUnsupported,
833 input0,
834 input1,
835 output,
836 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100837}
838
Jim Flynn906f9462019-05-10 13:55:21 +0100839bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
840 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000841 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100842 Optional<std::string&> reasonIfUnsupported) const
843{
Jim Flynne242f2d2019-05-22 14:24:13 +0100844 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
845 {
846 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
847 return false;
848 }
849
850 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
851 if(concatInnerAxis < 3) // Width, height, or channels
852 {
853 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
854 reasonIfUnsupported,
855 inputs,
856 output,
857 descriptor);
858 }
859 else if (concatInnerAxis == 3)
860 {
861 for (auto& input : inputs)
862 {
863 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
864 {
865 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
866 return false;
867 }
868 }
869 return true; // Sub-tensors support concat along batch
870 }
871 else // > 4 dimensions not supported.
872 {
873 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
874 return false;
875 }
Jim Flynn906f9462019-05-10 13:55:21 +0100876}
877
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100878bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
879 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000880{
Mike Kelly0886ac42020-04-27 09:55:40 +0100881 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
882 reasonIfUnsupported,
883 output);
telsoa014fcda012018-03-09 14:13:49 +0000884}
885
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100886bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
887 const TensorInfo& output,
888 Optional<std::string&> reasonIfUnsupported) const
889{
Jan Eilers8eb25602020-03-09 12:13:48 +0000890 armnn::IgnoreUnused(input);
891 armnn::IgnoreUnused(output);
892 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100893 return true;
894}
895
896bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
897 const TensorInfo& output,
898 Optional<std::string&> reasonIfUnsupported) const
899{
Jan Eilers8eb25602020-03-09 12:13:48 +0000900 armnn::IgnoreUnused(input);
901 armnn::IgnoreUnused(output);
902 armnn::IgnoreUnused(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100903 return true;
904}
905
906bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
907 const TensorInfo& output,
908 const Convolution2dDescriptor& descriptor,
909 const TensorInfo& weights,
910 const Optional<TensorInfo>& biases,
911 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000912{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100913 bool isFastMathEnabled = false;
914#if defined(ARMCOMPUTENEON_ENABLED)
915 if (m_ModelContextPtr)
916 {
917 if (m_ModelContextPtr.get() != nullptr)
918 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100919 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100920 if (modelOptions)
921 {
922 isFastMathEnabled = modelOptions->IsFastMathEnabled();
923 }
924 }
925 }
926#endif
927
surmeh013537c2c2018-05-18 16:31:43 +0100928 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
929 reasonIfUnsupported,
930 input,
931 output,
932 descriptor,
933 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100934 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000935 isFastMathEnabled,
936 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000937}
938
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100939bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
940 const TensorInfo& output,
941 const Convolution3dDescriptor& descriptor,
942 const TensorInfo& weights,
943 const Optional<TensorInfo>& biases,
944 Optional<std::string&> reasonIfUnsupported) const
945{
946 bool isFastMathEnabled = false;
947#if defined(ARMCOMPUTENEON_ENABLED)
948 if (m_ModelContextPtr)
949 {
950 if (m_ModelContextPtr.get() != nullptr)
951 {
952 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
953 if (modelOptions)
954 {
955 isFastMathEnabled = modelOptions->IsFastMathEnabled();
956 }
957 }
958 }
959#endif
960
961 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
962 reasonIfUnsupported,
963 input,
964 output,
965 descriptor,
966 weights,
967 biases,
968 isFastMathEnabled,
969 nullptr);
970}
971
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100972bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
973 const TensorInfo& output,
974 const DepthToSpaceDescriptor& descriptor,
975 Optional<std::string&> reasonIfUnsupported) const
976{
977 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
978 reasonIfUnsupported,
979 input,
980 output,
981 descriptor);
982}
983
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100984bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
985 const TensorInfo& output,
986 const DepthwiseConvolution2dDescriptor& descriptor,
987 const TensorInfo& weights,
988 const Optional<TensorInfo>& biases,
989 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000990{
telsoa01c577f2c2018-08-31 09:22:23 +0100991 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
992 reasonIfUnsupported,
993 input,
994 output,
995 descriptor,
996 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +0000997 biases,
998 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000999}
1000
Narumol Prangnawarat01961a72019-05-30 16:47:12 +01001001bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
1002 const TensorInfo& output,
1003 Optional<std::string&> reasonIfUnsupported) const
1004{
1005 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
1006 reasonIfUnsupported,
1007 input,
1008 output);
1009}
1010
Pablo Tellof0bd6832019-04-26 17:58:13 +01001011bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
1012 const TensorInfo& output,
1013 const DepthwiseConvolution2dDescriptor& descriptor,
1014 const TensorInfo& weights,
1015 const Optional<TensorInfo>& biases,
1016 Optional<std::string&> reasonIfUnsupported) const
1017{
1018 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1019 reasonIfUnsupported,
1020 input,
1021 output,
1022 descriptor,
1023 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001024 biases,
1025 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +01001026}
1027
josh minor4a3c6102020-01-06 16:40:46 -06001028bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
1029 const TensorInfo& output,
1030 const ElementwiseUnaryDescriptor& descriptor,
1031 Optional<std::string&> reasonIfUnsupported) const
1032{
Derek Lambertic77874a2020-04-28 13:34:56 +01001033 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -06001034 {
Derek Lambertic77874a2020-04-28 13:34:56 +01001035 case UnaryOperation::Abs:
1036 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
1037 reasonIfUnsupported,
1038 input,
1039 output);
1040 case UnaryOperation::Exp:
1041 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
1042 reasonIfUnsupported,
1043 input,
1044 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +01001045 case UnaryOperation::LogicalNot:
1046 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
1047 reasonIfUnsupported,
1048 input,
1049 output);
1050 case UnaryOperation::Log:
1051 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
1052 reasonIfUnsupported,
1053 input,
1054 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001055 case UnaryOperation::Neg:
1056 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
1057 reasonIfUnsupported,
1058 input,
1059 output);
1060 case UnaryOperation::Rsqrt:
1061 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
1062 reasonIfUnsupported,
1063 input,
1064 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +00001065 case UnaryOperation::Sin:
1066 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
1067 reasonIfUnsupported,
1068 input,
1069 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +01001070 case UnaryOperation::Sqrt:
1071 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
1072 reasonIfUnsupported,
1073 input,
1074 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001075 default:
1076 return false;
josh minor4a3c6102020-01-06 16:40:46 -06001077 }
josh minor4a3c6102020-01-06 16:40:46 -06001078}
1079
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001080bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
1081 const TensorInfo& output,
1082 const FillDescriptor& descriptor,
1083 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +01001084{
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001085 armnn::IgnoreUnused(input);
1086 armnn::IgnoreUnused(output);
1087 armnn::IgnoreUnused(descriptor);
1088
1089 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +01001090}
1091
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001092bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
1093 const TensorInfo& output,
1094 Optional<std::string&> reasonIfUnsupported) const
1095{
Jan Eilers8eb25602020-03-09 12:13:48 +00001096 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001097 return IsNeonBackendSupported(reasonIfUnsupported) &&
1098 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1099 input.GetDataType(),
1100 &FalseFuncF16<>,
1101 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001102 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001103 &FalseFuncI32<>,
1104 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001105}
1106
1107bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1108 const TensorInfo& output,
1109 const TensorInfo& weights,
1110 const TensorInfo& biases,
1111 const FullyConnectedDescriptor& descriptor,
1112 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001113{
telsoa01c577f2c2018-08-31 09:22:23 +01001114 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1115 reasonIfUnsupported,
1116 input,
1117 output,
1118 weights,
1119 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001120 descriptor,
1121 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001122}
1123
Teresa Charlinf540eb82020-04-10 19:24:55 +01001124bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1125 const TensorInfo& input1,
1126 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001127 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001128 Optional<std::string&> reasonIfUnsupported) const
1129{
1130 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1131 reasonIfUnsupported,
1132 input0,
1133 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001134 output,
1135 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001136}
1137
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001138bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1139 const TensorInfo& input1,
1140 const TensorInfo& output,
1141 Optional<std::string&> reasonIfUnsupported) const
1142{
1143 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1144 reasonIfUnsupported,
1145 input0,
1146 input1,
1147 output);
1148}
1149
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001150bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1151 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001152{
Derek Lamberti901ea112019-12-10 22:07:09 +00001153 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001154}
1155
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001156bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1157 const TensorInfo& output,
1158 const InstanceNormalizationDescriptor& descriptor,
1159 Optional<std::string&> reasonIfUnsupported) const
1160{
1161 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1162 reasonIfUnsupported,
1163 input,
1164 output,
1165 descriptor);
1166}
1167
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001168bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1169 const TensorInfo& output,
1170 const L2NormalizationDescriptor& descriptor,
1171 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001172{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001173 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001174}
1175
James Conroy177df1e2020-11-13 10:18:51 +00001176bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1177 const TensorInfo& input1,
1178 const TensorInfo& output,
1179 const LogicalBinaryDescriptor& descriptor,
1180 Optional<std::string&> reasonIfUnsupported) const
1181{
1182 switch(descriptor.m_Operation)
1183 {
1184 case LogicalBinaryOperation::LogicalAnd:
1185 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1186 reasonIfUnsupported,
1187 input0,
1188 input1,
1189 output);
1190 case LogicalBinaryOperation::LogicalOr:
1191 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1192 reasonIfUnsupported,
1193 input0,
1194 input1,
1195 output);
1196 default:
1197 return false;
1198 }
1199}
1200
Keith Davis69e653f2020-07-02 11:49:26 +01001201bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1202 const TensorInfo& output,
1203 const LogSoftmaxDescriptor& descriptor,
1204 Optional<std::string&> reasonIfUnsupported) const
1205{
1206 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1207}
1208
Jan Eilersad5293a2019-07-08 09:57:55 +01001209bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1210 const TensorInfo& outputStateIn,
1211 const TensorInfo& cellStateIn,
1212 const TensorInfo& scratchBuffer,
1213 const TensorInfo& outputStateOut,
1214 const TensorInfo& cellStateOut,
1215 const TensorInfo& output,
1216 const LstmDescriptor& descriptor,
1217 const LstmInputParamsInfo& paramsInfo,
1218 Optional<std::string&> reasonIfUnsupported) const
1219{
1220 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1221 reasonIfUnsupported,
1222 input,
1223 outputStateIn,
1224 cellStateIn,
1225 scratchBuffer,
1226 outputStateOut,
1227 cellStateOut,
1228 output,
1229 descriptor,
1230 paramsInfo);
1231}
1232
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001233bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1234 const TensorInfo& input1,
1235 const TensorInfo& output,
1236 Optional<std::string&> reasonIfUnsupported) const
1237{
1238 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1239 reasonIfUnsupported,
1240 input0,
1241 input1,
1242 output);
1243}
1244
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001245bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1246 const TensorInfo& output,
1247 const MeanDescriptor& descriptor,
1248 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001249{
Matthew Benthamfd899962018-12-31 15:49:42 +00001250 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1251 reasonIfUnsupported,
1252 input,
1253 output,
1254 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001255}
1256
Conor Kennedy54b21692019-01-09 07:57:38 +00001257bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1258 const TensorInfo& input1,
1259 const TensorInfo& output,
1260 Optional<std::string&> reasonIfUnsupported) const
1261{
1262 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1263 reasonIfUnsupported,
1264 input0,
1265 input1,
1266 output);
1267}
1268
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001269bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1270 const TensorInfo& input1,
1271 const TensorInfo& output,
1272 Optional<std::string&> reasonIfUnsupported) const
1273{
1274 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1275 reasonIfUnsupported,
1276 input0,
1277 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001278 output,
1279 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001280}
1281
Pablo Telloe61f0712020-01-23 10:37:17 +00001282bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1283 const TensorInfo& input1,
1284 const TensorInfo& output,
1285 Optional<std::string&> reasonIfUnsupported) const
1286{
1287 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1288 reasonIfUnsupported,
1289 input0,
1290 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001291 output,
1292 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001293}
1294
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001295bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1296 const TensorInfo& output,
1297 const NormalizationDescriptor& descriptor,
1298 Optional<std::string&> reasonIfUnsupported) const
1299{
1300 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1301 reasonIfUnsupported,
1302 input,
1303 output,
1304 descriptor);
1305}
1306
1307bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1308 Optional<std::string&> reasonIfUnsupported) const
1309{
Derek Lamberti901ea112019-12-10 22:07:09 +00001310 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001311}
1312
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001313bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1314 const TensorInfo& output,
1315 const PadDescriptor& descriptor,
1316 Optional<std::string&> reasonIfUnsupported) const
1317{
1318 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1319 reasonIfUnsupported,
1320 input,
1321 output,
1322 descriptor);
1323}
1324
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001325bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1326 const TensorInfo& output,
1327 const PermuteDescriptor& descriptor,
1328 Optional<std::string&> reasonIfUnsupported) const
1329{
1330 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001331}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001332
1333bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1334 const TensorInfo& output,
1335 const Pooling2dDescriptor& descriptor,
1336 Optional<std::string&> reasonIfUnsupported) const
1337{
1338 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1339}
1340
Ryan OShea19e79422022-05-04 00:38:03 +01001341bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1342 const TensorInfo& output,
1343 const Pooling3dDescriptor& descriptor,
1344 Optional<std::string&> reasonIfUnsupported) const
1345{
1346 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1347}
1348
Nikhil Raj9b461482019-07-03 15:58:31 +01001349bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1350 const armnn::TensorInfo &alpha,
1351 const armnn::TensorInfo &output,
1352 armnn::Optional<std::string &> reasonIfUnsupported) const
1353{
1354 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1355}
1356
James Conroycc340932020-05-12 18:08:52 +01001357bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1358 const TensorInfo& previousOutputIn,
1359 const TensorInfo& previousCellStateIn,
1360 const TensorInfo& outputStateOut,
1361 const TensorInfo& cellStateOut,
1362 const TensorInfo& output,
1363 const QLstmDescriptor& descriptor,
1364 const LstmInputParamsInfo& paramsInfo,
1365 Optional<std::string&> reasonIfUnsupported) const
1366{
1367 // Check required here in order to pass IsLayerSupported for datatypes tests
1368 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1369 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1370 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1371 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1372 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1373 output.GetDataType() == armnn::DataType::QAsymmS8)
1374 {
1375 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1376 reasonIfUnsupported,
1377 input,
1378 previousCellStateIn,
1379 previousOutputIn,
1380 cellStateOut,
1381 outputStateOut,
1382 output,
1383 descriptor,
1384 paramsInfo);
1385 }
1386 else
1387 {
1388 return false;
1389 }
1390}
1391
Sadik Armaganfabc2892019-05-31 09:05:11 +01001392bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1393 const TensorInfo& output,
1394 Optional<std::string&> reasonIfUnsupported) const
1395{
1396 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1397 reasonIfUnsupported,
1398 input,
1399 output);
1400}
1401
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001402bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1403 const TensorInfo& cellStateIn,
1404 const TensorInfo& outputStateIn,
1405 const TensorInfo& cellStateOut,
1406 const TensorInfo& outputStateOut,
1407 const QuantizedLstmInputParamsInfo& paramsInfo,
1408 Optional<std::string&> reasonIfUnsupported) const
1409{
1410 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1411 reasonIfUnsupported,
1412 input,
1413 cellStateIn,
1414 outputStateIn,
1415 cellStateOut,
1416 outputStateOut,
1417 paramsInfo);
1418}
1419
Sadik Armagana2747482021-02-09 10:28:54 +00001420bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1421 const TensorInfo& output,
1422 const ReduceDescriptor& descriptor,
1423 Optional<std::string&> reasonIfUnsupported) const
1424{
1425 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1426 reasonIfUnsupported,
1427 input,
1428 output,
1429 descriptor);
1430}
1431
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001432bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001433 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001434 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001435 Optional<std::string&> reasonIfUnsupported) const
1436{
Jan Eilers8eb25602020-03-09 12:13:48 +00001437 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001438 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1439 reasonIfUnsupported,
1440 input,
1441 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001442}
1443
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001444bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1445 const TensorInfo& output,
1446 const ResizeDescriptor& descriptor,
1447 Optional<std::string&> reasonIfUnsupported) const
1448{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001449 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1450 reasonIfUnsupported,
1451 input,
1452 output,
1453 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001454}
1455
josh minor036f02d2019-11-15 14:53:22 -06001456bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1457 const TensorInfo& output,
1458 const SliceDescriptor& descriptor,
1459 Optional<std::string&> reasonIfUnsupported) const
1460{
1461 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1462 reasonIfUnsupported,
1463 input,
1464 output,
1465 descriptor);
1466}
1467
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001468bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1469 const TensorInfo& output,
1470 const SoftmaxDescriptor& descriptor,
1471 Optional<std::string&> reasonIfUnsupported) const
1472{
1473 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1474}
1475
Mike Kelly0be3a882020-01-24 11:27:50 +00001476bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1477 const TensorInfo& output,
1478 const SpaceToBatchNdDescriptor& descriptor,
1479 Optional<std::string&> reasonIfUnsupported) const
1480{
1481 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1482 reasonIfUnsupported,
1483 input,
1484 output,
1485 descriptor);
1486}
1487
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001488bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001489 const TensorInfo& output,
1490 const SpaceToDepthDescriptor& descriptor,
1491 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001492{
1493 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1494 reasonIfUnsupported,
1495 input,
1496 output,
1497 descriptor);
1498}
1499
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001500bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001501 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1502 const ViewsDescriptor& descriptor,
1503 Optional<std::string&> reasonIfUnsupported) const
1504{
1505#if defined(ARMCOMPUTENEON_ENABLED)
1506 // Split along the last dimension, cannot use sub-tensors
1507 // as width and height of the sub-tensors do not match
1508 // the width and height of the parent tensor
1509 // in case of input with more than 2D.
1510 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1511 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1512 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1513 {
1514 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1515 reasonIfUnsupported,
1516 input,
1517 outputs,
1518 *splitAxis.begin());
1519 }
1520#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001521 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001522 for (auto output : outputs)
1523 {
1524 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1525 {
1526 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1527 return false;
1528 }
1529 }
1530 return true;
1531}
1532
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001533bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1534 const TensorInfo& output,
1535 const StackDescriptor& descriptor,
1536 Optional<std::string&> reasonIfUnsupported) const
1537{
1538 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1539 reasonIfUnsupported,
1540 inputs,
1541 output,
1542 descriptor);
1543}
1544
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001545bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1546 const TensorInfo& output,
1547 const StridedSliceDescriptor& descriptor,
1548 Optional<std::string&> reasonIfUnsupported) const
1549{
1550 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1551 reasonIfUnsupported,
1552 input,
1553 output,
1554 descriptor);
1555}
1556
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001557bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1558 const TensorInfo& input1,
1559 const TensorInfo& output,
1560 Optional<std::string&> reasonIfUnsupported) const
1561{
1562 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1563 reasonIfUnsupported,
1564 input0,
1565 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001566 output,
1567 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001568}
1569
Sadik Armagan581742d2019-08-12 14:11:37 +01001570bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1571 const TensorInfo& output,
1572 const TransposeConvolution2dDescriptor& descriptor,
1573 const TensorInfo& weights,
1574 const Optional<TensorInfo>& biases,
1575 Optional<std::string&> reasonIfUnsupported) const
1576{
1577 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1578 reasonIfUnsupported,
1579 input,
1580 output,
1581 descriptor,
1582 weights,
1583 biases);
1584}
1585
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001586bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1587 const TensorInfo& output,
1588 const TransposeDescriptor& descriptor,
1589 Optional<std::string&> reasonIfUnsupported) const
1590{
1591 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1592}
1593
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001594bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1595 const TensorInfo& outputStateIn,
1596 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001597 const TensorInfo& outputStateOut,
1598 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001599 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001600 const UnidirectionalSequenceLstmDescriptor& descriptor,
1601 const LstmInputParamsInfo& paramsInfo,
1602 Optional<std::string&> reasonIfUnsupported) const
1603{
Mike Kelly12994962022-04-21 11:57:09 +01001604 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1605 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1606 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1607 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1608 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1609 output.GetDataType() == armnn::DataType::QAsymmS8)
1610 {
1611 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1612 reasonIfUnsupported,
1613 input,
1614 outputStateIn,
1615 cellStateIn,
1616 outputStateOut,
1617 cellStateOut,
1618 output,
1619 descriptor,
1620 paramsInfo);
1621 }
1622 else
1623 {
1624 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1625 reasonIfUnsupported,
1626 input,
1627 outputStateIn,
1628 cellStateIn,
1629 outputStateOut,
1630 cellStateOut,
1631 output,
1632 descriptor,
1633 paramsInfo);
1634 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001635}
1636
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001637} // namespace armnn