blob: d097240022f8b8492e7699abde24273766ef5c58 [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"
Matthew Bentham34336f92023-04-27 12:13:50 +000035#include "workloads/NeonConvertFp16ToFp32Workload.hpp"
36#include "workloads/NeonConvertFp32ToFp16Workload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010037#include "workloads/NeonConvolution2dWorkload.hpp"
Teresa Charlinec5f7d12021-10-22 17:15:00 +010038#include "workloads/NeonConvolution3dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010039#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010040#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010041#include "workloads/NeonDequantizeWorkload.hpp"
John Mcloughlin34c1c382023-05-17 15:08:36 +010042#include "workloads/NeonElementwiseBinaryWorkload.hpp"
Teresa Charline89dd692021-09-01 16:30:34 +010043#include "workloads/NeonExpWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010044#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010045#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010046#include "workloads/NeonLogWorkload.hpp"
Keith Davis69e653f2020-07-02 11:49:26 +010047#include "workloads/NeonLogSoftmaxWorkload.hpp"
James Conroy177df1e2020-11-13 10:18:51 +000048#include "workloads/NeonLogicalAndWorkload.hpp"
49#include "workloads/NeonLogicalNotWorkload.hpp"
50#include "workloads/NeonLogicalOrWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010051#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000052#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000053#include "workloads/NeonMeanWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000054#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000055#include "workloads/NeonMultiplicationWorkload.hpp"
Pablo Telloe61f0712020-01-23 10:37:17 +000056#include "workloads/NeonDivisionWorkload.hpp"
Sadik Armaganac472102020-03-24 09:54:36 +000057#include "workloads/NeonNegWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010058#include "workloads/NeonNormalizationFloatWorkload.hpp"
59#include "workloads/NeonFullyConnectedWorkload.hpp"
Teresa Charlinf540eb82020-04-10 19:24:55 +010060#include "workloads/NeonGatherWorkload.hpp"
Teresa Charlinbd22c7d2022-04-26 18:14:12 +010061#include "workloads/NeonGatherNdWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000062#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010063#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010064#include "workloads/NeonPooling2dWorkload.hpp"
Ryan OShea19e79422022-05-04 00:38:03 +010065#include "workloads/NeonPooling3dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010066#include "workloads/NeonPreluWorkload.hpp"
James Conroycc340932020-05-12 18:08:52 +010067#include "workloads/NeonQLstmWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010068#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010069#include "workloads/NeonQuantizedLstmWorkload.hpp"
Sadik Armagana2747482021-02-09 10:28:54 +000070#include "workloads/NeonReduceWorkload.hpp"
Kevin Maya023c402019-12-12 17:28:05 +000071#include "workloads/NeonReshapeWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010072#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010073#include "workloads/NeonRsqrtWorkload.hpp"
Teresa Charlin50de4fa2021-05-31 18:47:33 +010074#include "workloads/NeonSinWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060075#include "workloads/NeonSliceWorkload.hpp"
Sadik Armaganbe88a572020-04-30 11:39:37 +010076#include "workloads/NeonSoftmaxWorkload.hpp"
Mike Kelly0be3a882020-01-24 11:27:50 +000077#include "workloads/NeonSpaceToBatchNdWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010078#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010079#include "workloads/NeonSplitterWorkload.hpp"
Teresa Charlin06145cc2022-05-05 15:31:30 +010080#include "workloads/NeonSqrtWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010081#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010082#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000083#include "workloads/NeonSubtractionWorkload.hpp"
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,
130 dataType,
131 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +0100132 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +0000133 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +0000134 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000135 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +0000136 std::forward<Params>(params)...);
137}
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);
432 case LayerType::Gather:
433 return support.IsGatherSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000434 infos[1],
435 infos[2],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000436 *(PolymorphicDowncast<const GatherDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000437 reasonIfUnsupported);
Teresa Charlinbd22c7d2022-04-26 18:14:12 +0100438 case LayerType::GatherNd:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000439 return support.IsGatherNdSupported(infos[0],
440 infos[1],
441 infos[2],
442 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000443 case LayerType::Input:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000444 return support.IsInputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000445 case LayerType::InstanceNormalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000446 return support.IsInstanceNormalizationSupported(infos[0],
447 infos[1],
448 *(PolymorphicDowncast<const
449 InstanceNormalizationDescriptor*>(&descriptor)),
450 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000451 case LayerType::L2Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000452 return support.IsL2NormalizationSupported(infos[0],
453 infos[1],
454 *(PolymorphicDowncast<const
455 L2NormalizationDescriptor*>(&descriptor)),
456 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000457 case LayerType::LogicalBinary:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000458 return support.IsLogicalBinarySupported(infos[0],
459 infos[1],
460 infos[2],
461 *(PolymorphicDowncast<const
462 LogicalBinaryDescriptor*>(&descriptor)),
463 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000464 case LayerType::LogSoftmax:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000465 return support.IsLogSoftmaxSupported(infos[0],
466 infos[1],
467 *(PolymorphicDowncast<const LogSoftmaxDescriptor*>(&descriptor)),
468 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000469 case LayerType::Lstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000470 return support.IsLstmSupported(infos[0],
471 infos[1],
472 infos[2],
473 infos[3],
474 infos[4],
475 infos[5],
476 infos[6],
477 *(PolymorphicDowncast<const LstmDescriptor*>(&descriptor)),
478 lstmParamsInfo.value(),
479 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000480 case LayerType::Map:
481 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000482 case LayerType::Maximum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000483 return support.IsMaximumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000484 case LayerType::Mean:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000485 return support.IsMeanSupported(infos[0],
486 infos[1],
487 *(PolymorphicDowncast<const MeanDescriptor*>(&descriptor)),
488 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000489 case LayerType::MemCopy:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000490 return support.IsMemCopySupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000491 case LayerType::MemImport:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000492 return support.IsMemImportSupported(infos[0], infos[1], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000493 case LayerType::Merge:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000494 return support.IsMergeSupported(infos[0],
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000495 infos[1],
496 infos[2],
497 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000498 case LayerType::Minimum:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000499 return support.IsMinimumSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000500 case LayerType::Multiplication:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000501 return support.IsMultiplicationSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000502 case LayerType::Normalization:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000503 return support.IsNormalizationSupported(infos[0],
504 infos[1],
505 *(PolymorphicDowncast<const
506 NormalizationDescriptor*>(&descriptor)),
507 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000508 case LayerType::Output:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000509 return support.IsOutputSupported(infos[0], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000510 case LayerType::Pad:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000511 return support.IsPadSupported(infos[0],
512 infos[1],
513 *(PolymorphicDowncast<const PadDescriptor*>(&descriptor)),
514 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000515 case LayerType::Permute:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000516 return support.IsPermuteSupported(infos[0],
517 infos[1],
518 *(PolymorphicDowncast<const PermuteDescriptor*>(&descriptor)),
519 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000520 case LayerType::Pooling2d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000521 return support.IsPooling2dSupported(infos[0],
522 infos[1],
523 *(PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor)),
524 reasonIfUnsupported);
Ryan OShea19e79422022-05-04 00:38:03 +0100525 case LayerType::Pooling3d:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000526 return support.IsPooling3dSupported(infos[0],
527 infos[1],
528 *(PolymorphicDowncast<const Pooling3dDescriptor*>(&descriptor)),
529 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000530 case LayerType::Prelu:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000531 return support.IsPreluSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000532 case LayerType::QLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000533 return support.IsQLstmSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000534 infos[1],
535 infos[2],
536 infos[3],
537 infos[4],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000538 infos[5],
539 *(PolymorphicDowncast<const QLstmDescriptor*>(&descriptor)),
540 lstmParamsInfo.value(),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000541 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000542 case LayerType::Quantize:
543 return support.IsQuantizeSupported(infos[0], infos[1], reasonIfUnsupported);
544 case LayerType::QuantizedLstm:
545 return support.IsQuantizedLstmSupported(infos[0],
546 infos[1],
547 infos[2],
548 infos[3],
549 infos[4],
550 quantizedLstmParamsInfo.value(),
551 reasonIfUnsupported);
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000552 case LayerType::Rank:
553 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000554 case LayerType::Reshape:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000555 return support.IsReshapeSupported(infos[0],
556 infos[1],
557 *(PolymorphicDowncast<const ReshapeDescriptor*>(&descriptor)),
558 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000559 case LayerType::Resize:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000560 return support.IsResizeSupported(infos[0],
Cathal Corbett34b429c2021-12-24 12:24:40 +0000561 infos[1],
Cathal Corbett80f71a82022-12-20 18:25:40 +0000562 *(PolymorphicDowncast<const ResizeDescriptor*>(&descriptor)),
Cathal Corbett34b429c2021-12-24 12:24:40 +0000563 reasonIfUnsupported);
Cathal Corbett80f71a82022-12-20 18:25:40 +0000564 case LayerType::Reduce:
565 return support.IsReduceSupported(infos[0],
566 infos[1],
567 *(PolymorphicDowncast<const ReduceDescriptor*>(&descriptor)),
568 reasonIfUnsupported);
569 case LayerType::Shape:
570 return support.IsShapeSupported(infos[0],
571 infos[1],
572 reasonIfUnsupported);
573 case LayerType::Slice:
574 return support.IsSliceSupported(infos[0],
575 infos[1],
576 *(PolymorphicDowncast<const SliceDescriptor*>(&descriptor)),
577 reasonIfUnsupported);
578 case LayerType::Softmax:
579 return support.IsSoftmaxSupported(infos[0],
580 infos[1],
581 *(PolymorphicDowncast<const SoftmaxDescriptor*>(&descriptor)),
582 reasonIfUnsupported);
583 case LayerType::SpaceToBatchNd:
584 return support.IsSpaceToBatchNdSupported(infos[0],
585 infos[1],
586 *(PolymorphicDowncast<const
587 SpaceToBatchNdDescriptor*>(&descriptor)),
588 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000589 case LayerType::SpaceToDepth:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000590 return support.IsSpaceToDepthSupported(infos[0],
591 infos[1],
592 *(PolymorphicDowncast<const SpaceToDepthDescriptor*>(&descriptor)),
593 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000594 case LayerType::Splitter:
595 {
596 std::vector<TensorInfo> outputInfos;
597 for (uint32_t i = 1; i < infos.size(); i++)
598 {
599 outputInfos.push_back(infos[i]);
600 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000601 return support.IsSplitterSupported(infos[0],
602 {outputInfos.begin(), outputInfos.end()},
603 *(PolymorphicDowncast<const ViewsDescriptor*>(&descriptor)),
604 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000605 }
606 case LayerType::Stack:
607 {
608 std::vector<const TensorInfo*> inputInfos;
609 for (uint32_t i = 0; i < infos.size() - 1; i++)
610 {
611 inputInfos.push_back(&infos[i]);
612 }
Cathal Corbett80f71a82022-12-20 18:25:40 +0000613 return support.IsStackSupported(inputInfos,
614 infos[infos.size() - 1],
615 *(PolymorphicDowncast<const StackDescriptor*>(&descriptor)),
616 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000617 }
618 case LayerType::StridedSlice:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000619 return support.IsStridedSliceSupported(infos[0],
620 infos[1],
621 *(PolymorphicDowncast<const StridedSliceDescriptor*>(&descriptor)),
622 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000623 case LayerType::Subtraction:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000624 return support.IsSubtractionSupported(infos[0], infos[1], infos[2], reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000625 case LayerType::Transpose:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000626 return support.IsTransposeSupported(infos[0],
627 infos[1],
628 *(PolymorphicDowncast<const TransposeDescriptor*>(&descriptor)),
629 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000630 case LayerType::TransposeConvolution2d:
631 {
632 if (infos.size() != 4)
633 {
634 throw InvalidArgumentException("Invalid number of TransposeConvolution2d TensorInfos. "
635 "TensorInfos should be of format: {input, output, weights, biases}.");
636 }
637
638 auto desc = *(PolymorphicDowncast<const TransposeConvolution2dDescriptor*>(&descriptor));
639 if (infos[3] == TensorInfo())
640 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000641 return support.IsTransposeConvolution2dSupported(infos[0],
642 infos[1],
643 desc,
644 infos[2],
645 EmptyOptional(),
646 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000647 }
648 else
649 {
Cathal Corbett80f71a82022-12-20 18:25:40 +0000650 return support.IsTransposeConvolution2dSupported(infos[0],
651 infos[1],
652 desc,
653 infos[2],
654 infos[3],
655 reasonIfUnsupported);
Cathal Corbett34b429c2021-12-24 12:24:40 +0000656 }
657 }
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000658 case LayerType::UnidirectionalSequenceLstm:
Cathal Corbett80f71a82022-12-20 18:25:40 +0000659 {
660 auto desc = *(PolymorphicDowncast<const UnidirectionalSequenceLstmDescriptor*>(&descriptor));
661 return support.IsUnidirectionalSequenceLstmSupported(infos[0],
662 infos[1],
663 infos[2],
664 infos[3],
665 infos[4],
666 infos[5],
667 desc,
668 lstmParamsInfo.value(),
669 reasonIfUnsupported);
670 }
Cathal Corbett34b429c2021-12-24 12:24:40 +0000671 case LayerType::Unmap:
672 return true;
Cathal Corbett34b429c2021-12-24 12:24:40 +0000673 default:
674 // layers not supported in neon by default:
Cathal Corbett4952a3e2022-03-03 15:14:18 +0000675 // debug, fakequantization, precompiled,
Ryan OShea19e79422022-05-04 00:38:03 +0100676 // standin, switch
Cathal Corbett34b429c2021-12-24 12:24:40 +0000677 return false;
678 }
679}
680
Cathal Corbett80f71a82022-12-20 18:25:40 +0000681bool NeonLayerSupport::IsLayerSupported(const LayerType& type,
682 const std::vector<TensorInfo>& infos,
683 const BaseDescriptor& descriptor,
684 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
685 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmParamsInfo,
686 Optional<std::string&> reasonIfUnsupported) const
687{
688 bool isSupported = IsLayerTypeSupported(type,
689 infos,
690 descriptor,
691 lstmParamsInfo,
692 quantizedLstmParamsInfo,
693 reasonIfUnsupported,
694 *this);
695
696 // For android-nn-driver and support library, to run FP16 operations on CpuAcc we need at least v8.2
697 // architecture. If the available architecture is older than v8.2, we can check if the operator is
698 // supported by changing operator inputs & outputs to be FP32.
699 // This does not change the operator datatype in the above parsers to be FP32. We are simply reporting
700 // to the parsers if the operator can supported in ArmNN. We will then re-enter ArmNN (Network.cpp)
701 // where we will recheck IsLayerSupported() on the FP16 datatype, update the operator to be FP32,
702 // and, insert convert layers around the FP32 operator.
703 if (reasonIfUnsupported.has_value())
704 {
705 std::string checkStr = "This CPU architecture does not support F16 data type, you need v8.2 or above";
706 if (!isSupported
707 && reasonIfUnsupported.value().find(checkStr) != std::string::npos)
708 {
709 std::vector<TensorInfo> newInfos;
710 for (auto info: infos)
711 {
712 newInfos.emplace_back(OverrideDataType(info, DataType::Float32));
713 }
714
715 std::string tmpString;
716 return IsLayerTypeSupported(type,
717 newInfos,
718 descriptor,
719 lstmParamsInfo,
720 quantizedLstmParamsInfo,
721 tmpString,
722 *this);
723 }
724 }
725
726 return isSupported;
727}
728
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100729bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
730 const TensorInfo& output,
731 const ActivationDescriptor& descriptor,
732 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000733{
Jan Eilers8eb25602020-03-09 12:13:48 +0000734 IgnoreUnused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100735 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
736 reasonIfUnsupported,
737 input,
738 output,
739 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000740}
741
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100742bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
743 const TensorInfo& input1,
744 const TensorInfo& output,
745 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000746{
telsoa01c577f2c2018-08-31 09:22:23 +0100747 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
748 reasonIfUnsupported,
749 input0,
750 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +0000751 output,
752 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000753}
754
James Conroyd47a0642019-09-17 14:22:06 +0100755bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
756 const TensorInfo& output,
757 const ArgMinMaxDescriptor& descriptor,
758 Optional<std::string&> reasonIfUnsupported) const
759{
760 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
761 reasonIfUnsupported,
762 input,
763 output,
764 descriptor);
765}
766
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100767bool NeonLayerSupport::IsBatchMatMulSupported(const TensorInfo& inputX,
768 const TensorInfo& inputY,
769 const TensorInfo& output,
770 const BatchMatMulDescriptor& descriptor,
771 Optional<std::string&> reasonIfUnsupported) const
772{
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000773 bool isFastMathEnabled = false;
774#if defined(ARMCOMPUTENEON_ENABLED)
775 if (m_ModelContextPtr)
776 {
777 if (m_ModelContextPtr.get() != nullptr)
778 {
779 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
780 if (modelOptions)
781 {
782 isFastMathEnabled = modelOptions->IsFastMathEnabled();
783 }
784 }
785 }
786#endif
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100787 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchMatMulValidate,
788 reasonIfUnsupported,
789 inputX,
790 inputY,
791 output,
Teresa Charlin1fe6c812022-11-01 15:59:50 +0000792 descriptor,
793 isFastMathEnabled,
794 nullptr);
Teresa Charlin0f86ecf2022-10-13 15:47:08 +0100795}
796
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100797bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
798 const TensorInfo& output,
799 const TensorInfo& mean,
800 const TensorInfo& var,
801 const TensorInfo& beta,
802 const TensorInfo& gamma,
803 const BatchNormalizationDescriptor& descriptor,
804 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000805{
telsoa01c577f2c2018-08-31 09:22:23 +0100806 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
807 reasonIfUnsupported,
808 input,
809 output,
810 mean,
811 var,
812 beta,
813 gamma,
Mike Kelly07810fc2020-11-12 10:58:48 +0000814 descriptor,
815 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000816}
817
Mike Kelly56858022020-01-27 12:14:47 +0000818bool NeonLayerSupport::IsBatchToSpaceNdSupported(const TensorInfo& input,
819 const TensorInfo& output,
820 const BatchToSpaceNdDescriptor& descriptor,
821 Optional<std::string&> reasonIfUnsupported) const
822{
823 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchToSpaceNdWorkloadValidate,
824 reasonIfUnsupported,
825 input,
826 output,
827 descriptor);
828}
829
Sadik Armagan48f011e2021-04-21 10:50:34 +0100830bool NeonLayerSupport::IsCastSupported(const TensorInfo& input,
831 const TensorInfo& output,
832 Optional<std::string&> reasonIfUnsupported) const
833{
834 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonCastValidate,
835 reasonIfUnsupported,
836 input,
837 output);
838}
839
Teresa Charline89dd692021-09-01 16:30:34 +0100840bool NeonLayerSupport::IsChannelShuffleSupported(const TensorInfo& input,
841 const TensorInfo& output,
842 const ChannelShuffleDescriptor& descriptor,
843 Optional<std::string&> reasonIfUnsupported) const
844{
845 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonChannelShuffleValidate,
846 reasonIfUnsupported,
847 input,
848 output,
849 descriptor);
850}
851
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100852bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
853 const TensorInfo& input1,
854 const TensorInfo& output,
855 const ComparisonDescriptor& descriptor,
856 Optional<std::string&> reasonIfUnsupported) const
857{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100858
Teresa Charlincedd34f2020-03-30 11:17:30 +0100859 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
860 reasonIfUnsupported,
861 input0,
862 input1,
863 output,
864 descriptor);
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100865}
866
Jim Flynn906f9462019-05-10 13:55:21 +0100867bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
868 const TensorInfo& output,
Cathal Corbett34b429c2021-12-24 12:24:40 +0000869 const OriginsDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100870 Optional<std::string&> reasonIfUnsupported) const
871{
Jim Flynne242f2d2019-05-22 14:24:13 +0100872 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
873 {
874 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
875 return false;
876 }
877
878 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
879 if(concatInnerAxis < 3) // Width, height, or channels
880 {
881 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
882 reasonIfUnsupported,
883 inputs,
884 output,
885 descriptor);
886 }
887 else if (concatInnerAxis == 3)
888 {
889 for (auto& input : inputs)
890 {
891 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
892 {
893 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
894 return false;
895 }
896 }
897 return true; // Sub-tensors support concat along batch
898 }
899 else // > 4 dimensions not supported.
900 {
901 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
902 return false;
903 }
Jim Flynn906f9462019-05-10 13:55:21 +0100904}
905
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100906bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
907 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000908{
Mike Kelly0886ac42020-04-27 09:55:40 +0100909 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConstantWorkloadValidate,
910 reasonIfUnsupported,
911 output);
telsoa014fcda012018-03-09 14:13:49 +0000912}
913
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100914bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
915 const TensorInfo& output,
916 Optional<std::string&> reasonIfUnsupported) const
917{
Matthew Bentham34336f92023-04-27 12:13:50 +0000918 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp16ToFp32WorkloadValidate,
919 reasonIfUnsupported,
920 input,
921 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100922}
923
924bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
925 const TensorInfo& output,
926 Optional<std::string&> reasonIfUnsupported) const
927{
Matthew Bentham34336f92023-04-27 12:13:50 +0000928 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvertFp32ToFp16WorkloadValidate,
929 reasonIfUnsupported,
930 input,
931 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100932}
933
934bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
935 const TensorInfo& output,
936 const Convolution2dDescriptor& descriptor,
937 const TensorInfo& weights,
938 const Optional<TensorInfo>& biases,
939 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000940{
Sadik Armagan045f6be2020-09-10 13:37:32 +0100941 bool isFastMathEnabled = false;
942#if defined(ARMCOMPUTENEON_ENABLED)
943 if (m_ModelContextPtr)
944 {
945 if (m_ModelContextPtr.get() != nullptr)
946 {
Sadik Armagan04a72972020-09-14 15:44:18 +0100947 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
Sadik Armagan045f6be2020-09-10 13:37:32 +0100948 if (modelOptions)
949 {
950 isFastMathEnabled = modelOptions->IsFastMathEnabled();
951 }
952 }
953 }
954#endif
955
surmeh013537c2c2018-05-18 16:31:43 +0100956 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
957 reasonIfUnsupported,
958 input,
959 output,
960 descriptor,
961 weights,
Sadik Armagan045f6be2020-09-10 13:37:32 +0100962 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +0000963 isFastMathEnabled,
964 nullptr);
telsoa014fcda012018-03-09 14:13:49 +0000965}
966
Teresa Charlinec5f7d12021-10-22 17:15:00 +0100967bool NeonLayerSupport::IsConvolution3dSupported(const TensorInfo& input,
968 const TensorInfo& output,
969 const Convolution3dDescriptor& descriptor,
970 const TensorInfo& weights,
971 const Optional<TensorInfo>& biases,
972 Optional<std::string&> reasonIfUnsupported) const
973{
974 bool isFastMathEnabled = false;
975#if defined(ARMCOMPUTENEON_ENABLED)
976 if (m_ModelContextPtr)
977 {
978 if (m_ModelContextPtr.get() != nullptr)
979 {
980 auto modelOptions = dynamic_cast<NeonBackendModelContext*>(m_ModelContextPtr.get());
981 if (modelOptions)
982 {
983 isFastMathEnabled = modelOptions->IsFastMathEnabled();
984 }
985 }
986 }
987#endif
988
989 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution3dWorkloadValidate,
990 reasonIfUnsupported,
991 input,
992 output,
993 descriptor,
994 weights,
995 biases,
996 isFastMathEnabled,
997 nullptr);
998}
999
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +01001000bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
1001 const TensorInfo& output,
1002 const DepthToSpaceDescriptor& descriptor,
1003 Optional<std::string&> reasonIfUnsupported) const
1004{
1005 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
1006 reasonIfUnsupported,
1007 input,
1008 output,
1009 descriptor);
1010}
1011
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001012bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
1013 const TensorInfo& output,
1014 const DepthwiseConvolution2dDescriptor& descriptor,
1015 const TensorInfo& weights,
1016 const Optional<TensorInfo>& biases,
1017 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001018{
telsoa01c577f2c2018-08-31 09:22:23 +01001019 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1020 reasonIfUnsupported,
1021 input,
1022 output,
1023 descriptor,
1024 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001025 biases,
1026 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001027}
1028
Narumol Prangnawarat01961a72019-05-30 16:47:12 +01001029bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
1030 const TensorInfo& output,
1031 Optional<std::string&> reasonIfUnsupported) const
1032{
1033 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
1034 reasonIfUnsupported,
1035 input,
1036 output);
1037}
1038
Pablo Tellof0bd6832019-04-26 17:58:13 +01001039bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
1040 const TensorInfo& output,
1041 const DepthwiseConvolution2dDescriptor& descriptor,
1042 const TensorInfo& weights,
1043 const Optional<TensorInfo>& biases,
1044 Optional<std::string&> reasonIfUnsupported) const
1045{
1046 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
1047 reasonIfUnsupported,
1048 input,
1049 output,
1050 descriptor,
1051 weights,
Mike Kelly07810fc2020-11-12 10:58:48 +00001052 biases,
1053 nullptr);
Pablo Tellof0bd6832019-04-26 17:58:13 +01001054}
1055
josh minor4a3c6102020-01-06 16:40:46 -06001056bool NeonLayerSupport::IsElementwiseUnarySupported(const TensorInfo& input,
1057 const TensorInfo& output,
1058 const ElementwiseUnaryDescriptor& descriptor,
1059 Optional<std::string&> reasonIfUnsupported) const
1060{
Derek Lambertic77874a2020-04-28 13:34:56 +01001061 switch(descriptor.m_Operation)
josh minor4a3c6102020-01-06 16:40:46 -06001062 {
Derek Lambertic77874a2020-04-28 13:34:56 +01001063 case UnaryOperation::Abs:
1064 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
1065 reasonIfUnsupported,
1066 input,
1067 output);
1068 case UnaryOperation::Exp:
1069 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonExpWorkloadValidate,
1070 reasonIfUnsupported,
1071 input,
1072 output);
Teresa Charlin50de4fa2021-05-31 18:47:33 +01001073 case UnaryOperation::LogicalNot:
1074 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalNotWorkloadValidate,
1075 reasonIfUnsupported,
1076 input,
1077 output);
1078 case UnaryOperation::Log:
1079 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogWorkloadValidate,
1080 reasonIfUnsupported,
1081 input,
1082 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001083 case UnaryOperation::Neg:
1084 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNegWorkloadValidate,
1085 reasonIfUnsupported,
1086 input,
1087 output);
1088 case UnaryOperation::Rsqrt:
1089 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate,
1090 reasonIfUnsupported,
1091 input,
1092 output);
ryan.oshea3cff135b2021-10-07 15:28:14 +00001093 case UnaryOperation::Sin:
1094 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSinWorkloadValidate,
1095 reasonIfUnsupported,
1096 input,
1097 output);
Teresa Charlin06145cc2022-05-05 15:31:30 +01001098 case UnaryOperation::Sqrt:
1099 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSqrtWorkloadValidate,
1100 reasonIfUnsupported,
1101 input,
1102 output);
Derek Lambertic77874a2020-04-28 13:34:56 +01001103 default:
1104 return false;
josh minor4a3c6102020-01-06 16:40:46 -06001105 }
josh minor4a3c6102020-01-06 16:40:46 -06001106}
1107
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001108bool NeonLayerSupport::IsFillSupported(const TensorInfo& input,
1109 const TensorInfo& output,
1110 const FillDescriptor& descriptor,
1111 Optional<std::string&> reasonIfUnsupported) const
Sadik Armagana792a052020-06-23 16:22:23 +01001112{
Teresa Charlin4b10fef2020-07-29 09:36:41 +01001113 armnn::IgnoreUnused(input);
1114 armnn::IgnoreUnused(output);
1115 armnn::IgnoreUnused(descriptor);
1116
1117 return IsNeonBackendSupported(reasonIfUnsupported);
Sadik Armagana792a052020-06-23 16:22:23 +01001118}
1119
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001120bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
1121 const TensorInfo& output,
1122 Optional<std::string&> reasonIfUnsupported) const
1123{
Jan Eilers8eb25602020-03-09 12:13:48 +00001124 armnn::IgnoreUnused(output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001125 return IsNeonBackendSupported(reasonIfUnsupported) &&
1126 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
1127 input.GetDataType(),
1128 &FalseFuncF16<>,
1129 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +00001130 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +00001131 &FalseFuncI32<>,
1132 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001133}
1134
1135bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
1136 const TensorInfo& output,
1137 const TensorInfo& weights,
1138 const TensorInfo& biases,
1139 const FullyConnectedDescriptor& descriptor,
1140 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001141{
telsoa01c577f2c2018-08-31 09:22:23 +01001142 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
1143 reasonIfUnsupported,
1144 input,
1145 output,
1146 weights,
1147 biases,
Mike Kelly07810fc2020-11-12 10:58:48 +00001148 descriptor,
1149 nullptr);
telsoa014fcda012018-03-09 14:13:49 +00001150}
1151
Teresa Charlinf540eb82020-04-10 19:24:55 +01001152bool NeonLayerSupport::IsGatherSupported(const TensorInfo& input0,
1153 const TensorInfo& input1,
1154 const TensorInfo& output,
Teresa Charlin52664732020-06-29 16:27:03 +01001155 const GatherDescriptor& descriptor,
Teresa Charlinf540eb82020-04-10 19:24:55 +01001156 Optional<std::string&> reasonIfUnsupported) const
1157{
1158 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherWorkloadValidate,
1159 reasonIfUnsupported,
1160 input0,
1161 input1,
Teresa Charlin52664732020-06-29 16:27:03 +01001162 output,
1163 descriptor);
Teresa Charlinf540eb82020-04-10 19:24:55 +01001164}
1165
Teresa Charlinbd22c7d2022-04-26 18:14:12 +01001166bool NeonLayerSupport::IsGatherNdSupported(const TensorInfo& input0,
1167 const TensorInfo& input1,
1168 const TensorInfo& output,
1169 Optional<std::string&> reasonIfUnsupported) const
1170{
1171 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGatherNdWorkloadValidate,
1172 reasonIfUnsupported,
1173 input0,
1174 input1,
1175 output);
1176}
1177
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001178bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
1179 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001180{
Derek Lamberti901ea112019-12-10 22:07:09 +00001181 return IsNeonBackendSupported(reasonIfUnsupported, input);
telsoa014fcda012018-03-09 14:13:49 +00001182}
1183
Sadik Armagan0d4863d2019-10-09 14:26:32 +01001184bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
1185 const TensorInfo& output,
1186 const InstanceNormalizationDescriptor& descriptor,
1187 Optional<std::string&> reasonIfUnsupported) const
1188{
1189 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
1190 reasonIfUnsupported,
1191 input,
1192 output,
1193 descriptor);
1194}
1195
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001196bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
1197 const TensorInfo& output,
1198 const L2NormalizationDescriptor& descriptor,
1199 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +00001200{
Matteo Martincighbcd3c852018-09-28 14:14:12 +01001201 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001202}
1203
James Conroy177df1e2020-11-13 10:18:51 +00001204bool NeonLayerSupport::IsLogicalBinarySupported(const TensorInfo& input0,
1205 const TensorInfo& input1,
1206 const TensorInfo& output,
1207 const LogicalBinaryDescriptor& descriptor,
1208 Optional<std::string&> reasonIfUnsupported) const
1209{
1210 switch(descriptor.m_Operation)
1211 {
1212 case LogicalBinaryOperation::LogicalAnd:
1213 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalAndWorkloadValidate,
1214 reasonIfUnsupported,
1215 input0,
1216 input1,
1217 output);
1218 case LogicalBinaryOperation::LogicalOr:
1219 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogicalOrWorkloadValidate,
1220 reasonIfUnsupported,
1221 input0,
1222 input1,
1223 output);
1224 default:
1225 return false;
1226 }
1227}
1228
Keith Davis69e653f2020-07-02 11:49:26 +01001229bool NeonLayerSupport::IsLogSoftmaxSupported(const TensorInfo& input,
1230 const TensorInfo& output,
1231 const LogSoftmaxDescriptor& descriptor,
1232 Optional<std::string&> reasonIfUnsupported) const
1233{
1234 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLogSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1235}
1236
Jan Eilersad5293a2019-07-08 09:57:55 +01001237bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
1238 const TensorInfo& outputStateIn,
1239 const TensorInfo& cellStateIn,
1240 const TensorInfo& scratchBuffer,
1241 const TensorInfo& outputStateOut,
1242 const TensorInfo& cellStateOut,
1243 const TensorInfo& output,
1244 const LstmDescriptor& descriptor,
1245 const LstmInputParamsInfo& paramsInfo,
1246 Optional<std::string&> reasonIfUnsupported) const
1247{
1248 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
1249 reasonIfUnsupported,
1250 input,
1251 outputStateIn,
1252 cellStateIn,
1253 scratchBuffer,
1254 outputStateOut,
1255 cellStateOut,
1256 output,
1257 descriptor,
1258 paramsInfo);
1259}
1260
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +00001261bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
1262 const TensorInfo& input1,
1263 const TensorInfo& output,
1264 Optional<std::string&> reasonIfUnsupported) const
1265{
1266 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
1267 reasonIfUnsupported,
1268 input0,
1269 input1,
1270 output);
1271}
1272
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001273bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
1274 const TensorInfo& output,
1275 const MeanDescriptor& descriptor,
1276 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +01001277{
Matthew Benthamfd899962018-12-31 15:49:42 +00001278 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
1279 reasonIfUnsupported,
1280 input,
1281 output,
1282 descriptor);
narpra0132b90462018-09-13 11:07:48 +01001283}
1284
Conor Kennedy54b21692019-01-09 07:57:38 +00001285bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
1286 const TensorInfo& input1,
1287 const TensorInfo& output,
1288 Optional<std::string&> reasonIfUnsupported) const
1289{
1290 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
1291 reasonIfUnsupported,
1292 input0,
1293 input1,
1294 output);
1295}
1296
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001297bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
1298 const TensorInfo& input1,
1299 const TensorInfo& output,
1300 Optional<std::string&> reasonIfUnsupported) const
1301{
1302 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
1303 reasonIfUnsupported,
1304 input0,
1305 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001306 output,
1307 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001308}
1309
Pablo Telloe61f0712020-01-23 10:37:17 +00001310bool NeonLayerSupport::IsDivisionSupported(const TensorInfo& input0,
1311 const TensorInfo& input1,
1312 const TensorInfo& output,
1313 Optional<std::string&> reasonIfUnsupported) const
1314{
1315 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDivisionWorkloadValidate,
1316 reasonIfUnsupported,
1317 input0,
1318 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001319 output,
1320 nullptr);
Pablo Telloe61f0712020-01-23 10:37:17 +00001321}
1322
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001323bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
1324 const TensorInfo& output,
1325 const NormalizationDescriptor& descriptor,
1326 Optional<std::string&> reasonIfUnsupported) const
1327{
1328 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
1329 reasonIfUnsupported,
1330 input,
1331 output,
1332 descriptor);
1333}
1334
1335bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
1336 Optional<std::string&> reasonIfUnsupported) const
1337{
Derek Lamberti901ea112019-12-10 22:07:09 +00001338 return IsNeonBackendSupported(reasonIfUnsupported, output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001339}
1340
Éanna Ó Catháin12055742019-01-25 10:01:40 +00001341bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
1342 const TensorInfo& output,
1343 const PadDescriptor& descriptor,
1344 Optional<std::string&> reasonIfUnsupported) const
1345{
1346 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
1347 reasonIfUnsupported,
1348 input,
1349 output,
1350 descriptor);
1351}
1352
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001353bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
1354 const TensorInfo& output,
1355 const PermuteDescriptor& descriptor,
1356 Optional<std::string&> reasonIfUnsupported) const
1357{
1358 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +00001359}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001360
1361bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
1362 const TensorInfo& output,
1363 const Pooling2dDescriptor& descriptor,
1364 Optional<std::string&> reasonIfUnsupported) const
1365{
1366 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1367}
1368
Ryan OShea19e79422022-05-04 00:38:03 +01001369bool NeonLayerSupport::IsPooling3dSupported(const TensorInfo& input,
1370 const TensorInfo& output,
1371 const Pooling3dDescriptor& descriptor,
1372 Optional<std::string&> reasonIfUnsupported) const
1373{
1374 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling3dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1375}
1376
Nikhil Raj9b461482019-07-03 15:58:31 +01001377bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
1378 const armnn::TensorInfo &alpha,
1379 const armnn::TensorInfo &output,
1380 armnn::Optional<std::string &> reasonIfUnsupported) const
1381{
1382 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
1383}
1384
James Conroycc340932020-05-12 18:08:52 +01001385bool NeonLayerSupport::IsQLstmSupported(const TensorInfo& input,
1386 const TensorInfo& previousOutputIn,
1387 const TensorInfo& previousCellStateIn,
1388 const TensorInfo& outputStateOut,
1389 const TensorInfo& cellStateOut,
1390 const TensorInfo& output,
1391 const QLstmDescriptor& descriptor,
1392 const LstmInputParamsInfo& paramsInfo,
1393 Optional<std::string&> reasonIfUnsupported) const
1394{
1395 // Check required here in order to pass IsLayerSupported for datatypes tests
1396 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1397 previousOutputIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1398 previousCellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1399 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1400 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1401 output.GetDataType() == armnn::DataType::QAsymmS8)
1402 {
1403 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQLstmWorkloadValidate,
1404 reasonIfUnsupported,
1405 input,
1406 previousCellStateIn,
1407 previousOutputIn,
1408 cellStateOut,
1409 outputStateOut,
1410 output,
1411 descriptor,
1412 paramsInfo);
1413 }
1414 else
1415 {
1416 return false;
1417 }
1418}
1419
Sadik Armaganfabc2892019-05-31 09:05:11 +01001420bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
1421 const TensorInfo& output,
1422 Optional<std::string&> reasonIfUnsupported) const
1423{
1424 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
1425 reasonIfUnsupported,
1426 input,
1427 output);
1428}
1429
Francis Murtagh4fc3c482019-08-02 13:20:54 +01001430bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
1431 const TensorInfo& cellStateIn,
1432 const TensorInfo& outputStateIn,
1433 const TensorInfo& cellStateOut,
1434 const TensorInfo& outputStateOut,
1435 const QuantizedLstmInputParamsInfo& paramsInfo,
1436 Optional<std::string&> reasonIfUnsupported) const
1437{
1438 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
1439 reasonIfUnsupported,
1440 input,
1441 cellStateIn,
1442 outputStateIn,
1443 cellStateOut,
1444 outputStateOut,
1445 paramsInfo);
1446}
1447
Sadik Armagana2747482021-02-09 10:28:54 +00001448bool NeonLayerSupport::IsReduceSupported(const TensorInfo& input,
1449 const TensorInfo& output,
1450 const ReduceDescriptor& descriptor,
1451 Optional<std::string&> reasonIfUnsupported) const
1452{
1453 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReduceWorkloadValidate,
1454 reasonIfUnsupported,
1455 input,
1456 output,
1457 descriptor);
1458}
1459
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001460bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Kevin Maya023c402019-12-12 17:28:05 +00001461 const TensorInfo& output,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +00001462 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001463 Optional<std::string&> reasonIfUnsupported) const
1464{
Jan Eilers8eb25602020-03-09 12:13:48 +00001465 armnn::IgnoreUnused(descriptor);
Kevin Maya023c402019-12-12 17:28:05 +00001466 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonReshapeWorkloadValidate,
1467 reasonIfUnsupported,
1468 input,
1469 output);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001470}
1471
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001472bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
1473 const TensorInfo& output,
1474 const ResizeDescriptor& descriptor,
1475 Optional<std::string&> reasonIfUnsupported) const
1476{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +01001477 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
1478 reasonIfUnsupported,
1479 input,
1480 output,
1481 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +01001482}
1483
josh minor036f02d2019-11-15 14:53:22 -06001484bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
1485 const TensorInfo& output,
1486 const SliceDescriptor& descriptor,
1487 Optional<std::string&> reasonIfUnsupported) const
1488{
1489 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
1490 reasonIfUnsupported,
1491 input,
1492 output,
1493 descriptor);
1494}
1495
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001496bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
1497 const TensorInfo& output,
1498 const SoftmaxDescriptor& descriptor,
1499 Optional<std::string&> reasonIfUnsupported) const
1500{
1501 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1502}
1503
Mike Kelly0be3a882020-01-24 11:27:50 +00001504bool NeonLayerSupport::IsSpaceToBatchNdSupported(const TensorInfo& input,
1505 const TensorInfo& output,
1506 const SpaceToBatchNdDescriptor& descriptor,
1507 Optional<std::string&> reasonIfUnsupported) const
1508{
1509 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToBatchNdWorkloadValidate,
1510 reasonIfUnsupported,
1511 input,
1512 output,
1513 descriptor);
1514}
1515
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001516bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
Mike Kelly0be3a882020-01-24 11:27:50 +00001517 const TensorInfo& output,
1518 const SpaceToDepthDescriptor& descriptor,
1519 Optional<std::string&> reasonIfUnsupported) const
Ellen Norris-Thompson29794572019-06-26 16:40:36 +01001520{
1521 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
1522 reasonIfUnsupported,
1523 input,
1524 output,
1525 descriptor);
1526}
1527
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001528bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001529 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
1530 const ViewsDescriptor& descriptor,
1531 Optional<std::string&> reasonIfUnsupported) const
1532{
1533#if defined(ARMCOMPUTENEON_ENABLED)
1534 // Split along the last dimension, cannot use sub-tensors
1535 // as width and height of the sub-tensors do not match
1536 // the width and height of the parent tensor
1537 // in case of input with more than 2D.
1538 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
1539 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
1540 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
1541 {
1542 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
1543 reasonIfUnsupported,
1544 input,
1545 outputs,
1546 *splitAxis.begin());
1547 }
1548#endif
Jan Eilers8eb25602020-03-09 12:13:48 +00001549 IgnoreUnused(descriptor);
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +01001550 for (auto output : outputs)
1551 {
1552 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
1553 {
1554 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
1555 return false;
1556 }
1557 }
1558 return true;
1559}
1560
Matthew Jackson87f65ea2019-08-01 10:01:34 +01001561bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
1562 const TensorInfo& output,
1563 const StackDescriptor& descriptor,
1564 Optional<std::string&> reasonIfUnsupported) const
1565{
1566 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
1567 reasonIfUnsupported,
1568 inputs,
1569 output,
1570 descriptor);
1571}
1572
FinnWilliamsArm1fa19192019-08-02 17:26:31 +01001573bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
1574 const TensorInfo& output,
1575 const StridedSliceDescriptor& descriptor,
1576 Optional<std::string&> reasonIfUnsupported) const
1577{
1578 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
1579 reasonIfUnsupported,
1580 input,
1581 output,
1582 descriptor);
1583}
1584
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001585bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
1586 const TensorInfo& input1,
1587 const TensorInfo& output,
1588 Optional<std::string&> reasonIfUnsupported) const
1589{
1590 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
1591 reasonIfUnsupported,
1592 input0,
1593 input1,
Mike Kelly07810fc2020-11-12 10:58:48 +00001594 output,
1595 nullptr);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001596}
1597
Sadik Armagan581742d2019-08-12 14:11:37 +01001598bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
1599 const TensorInfo& output,
1600 const TransposeConvolution2dDescriptor& descriptor,
1601 const TensorInfo& weights,
1602 const Optional<TensorInfo>& biases,
1603 Optional<std::string&> reasonIfUnsupported) const
1604{
1605 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
1606 reasonIfUnsupported,
1607 input,
1608 output,
1609 descriptor,
1610 weights,
1611 biases);
1612}
1613
Mike Kellyc9ea45a2020-02-28 18:11:58 +00001614bool NeonLayerSupport::IsTransposeSupported(const TensorInfo& input,
1615 const TensorInfo& output,
1616 const TransposeDescriptor& descriptor,
1617 Optional<std::string&> reasonIfUnsupported) const
1618{
1619 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
1620}
1621
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001622bool NeonLayerSupport::IsUnidirectionalSequenceLstmSupported(const TensorInfo& input,
1623 const TensorInfo& outputStateIn,
1624 const TensorInfo& cellStateIn,
Mike Kelly12994962022-04-21 11:57:09 +01001625 const TensorInfo& outputStateOut,
1626 const TensorInfo& cellStateOut,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001627 const TensorInfo& output,
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001628 const UnidirectionalSequenceLstmDescriptor& descriptor,
1629 const LstmInputParamsInfo& paramsInfo,
1630 Optional<std::string&> reasonIfUnsupported) const
1631{
Mike Kelly12994962022-04-21 11:57:09 +01001632 if (input.GetDataType() == armnn::DataType::QAsymmS8 &&
1633 outputStateIn.GetDataType() == armnn::DataType::QAsymmS8 &&
1634 cellStateIn.GetDataType() == armnn::DataType::QSymmS16 &&
1635 outputStateOut.GetDataType() == armnn::DataType::QAsymmS8 &&
1636 cellStateOut.GetDataType() == armnn::DataType::QSymmS16 &&
1637 output.GetDataType() == armnn::DataType::QAsymmS8)
1638 {
1639 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmWorkloadValidate,
1640 reasonIfUnsupported,
1641 input,
1642 outputStateIn,
1643 cellStateIn,
1644 outputStateOut,
1645 cellStateOut,
1646 output,
1647 descriptor,
1648 paramsInfo);
1649 }
1650 else
1651 {
1652 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonUnidirectionalSequenceLstmFloatWorkloadValidate,
1653 reasonIfUnsupported,
1654 input,
1655 outputStateIn,
1656 cellStateIn,
1657 outputStateOut,
1658 cellStateOut,
1659 output,
1660 descriptor,
1661 paramsInfo);
1662 }
Cathal Corbettfd5bec42022-03-03 15:13:23 +00001663}
1664
Aron Virginas-Tarfc824312018-10-15 15:00:13 +01001665} // namespace armnn