blob: 5410ef42dfc54363f5d87878df8dddd295578b58 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. 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"
telsoa014fcda012018-03-09 14:13:49 +00008
telsoa014fcda012018-03-09 14:13:49 +00009#include <armnn/Descriptors.hpp>
telsoa014fcda012018-03-09 14:13:49 +000010#include <armnn/Tensor.hpp>
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010011#include <armnn/Types.hpp>
Matteo Martincighc601aa62019-10-29 15:03:22 +000012#include <armnn/BackendRegistry.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
Matteo Martincighc601aa62019-10-29 15:03:22 +000014#include <InternalTypes.hpp>
15#include <LayerSupportCommon.hpp>
David Beck3e9e1152018-10-17 14:17:50 +010016
telsoa014fcda012018-03-09 14:13:49 +000017#include <boost/core/ignore_unused.hpp>
18
Matteo Martincighd95e9062019-01-31 15:35:59 +000019#if defined(ARMCOMPUTENEON_ENABLED)
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010020#include <aclCommon/ArmComputeUtils.hpp>
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +010021#include "workloads/NeonAbsWorkload.hpp"
Matthew Bentham955258d2018-12-10 10:48:52 +000022#include "workloads/NeonAdditionWorkload.hpp"
Nattapat Chaimanowongd4b70592018-10-12 11:21:49 +010023#include "workloads/NeonActivationWorkload.hpp"
James Conroyd47a0642019-09-17 14:22:06 +010024#include "workloads/NeonArgMinMaxWorkload.hpp"
Matthew Benthamc48ac8c2018-12-12 16:15:59 +000025#include "workloads/NeonBatchNormalizationWorkload.hpp"
Nattapat Chaimanowong974b65f2018-10-15 15:07:34 +010026#include "workloads/NeonConvolution2dWorkload.hpp"
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +010027#include "workloads/NeonDepthToSpaceWorkload.hpp"
Nattapat Chaimanowong77140882018-10-17 11:12:19 +010028#include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
Narumol Prangnawarat01961a72019-05-30 16:47:12 +010029#include "workloads/NeonDequantizeWorkload.hpp"
kevmay01eed85922019-01-28 08:37:25 +000030#include "workloads/NeonGreaterWorkload.hpp"
Sadik Armagan0d4863d2019-10-09 14:26:32 +010031#include "workloads/NeonInstanceNormalizationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010032#include "workloads/NeonL2NormalizationFloatWorkload.hpp"
Jan Eilersad5293a2019-07-08 09:57:55 +010033#include "workloads/NeonLstmFloatWorkload.hpp"
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +000034#include "workloads/NeonMaximumWorkload.hpp"
Matthew Benthamfd899962018-12-31 15:49:42 +000035#include "workloads/NeonMeanWorkload.hpp"
Jim Flynn39d487d2019-05-17 15:44:36 +010036#include "workloads/NeonConcatWorkload.hpp"
Conor Kennedy54b21692019-01-09 07:57:38 +000037#include "workloads/NeonMinimumWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000038#include "workloads/NeonMultiplicationWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010039#include "workloads/NeonNormalizationFloatWorkload.hpp"
40#include "workloads/NeonFullyConnectedWorkload.hpp"
Éanna Ó Catháin12055742019-01-25 10:01:40 +000041#include "workloads/NeonPadWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010042#include "workloads/NeonPermuteWorkload.hpp"
Nattapat Chaimanowong5d2e7002018-10-12 16:03:56 +010043#include "workloads/NeonPooling2dWorkload.hpp"
Nikhil Raj9b461482019-07-03 15:58:31 +010044#include "workloads/NeonPreluWorkload.hpp"
Sadik Armaganfabc2892019-05-31 09:05:11 +010045#include "workloads/NeonQuantizeWorkload.hpp"
Francis Murtagh4fc3c482019-08-02 13:20:54 +010046#include "workloads/NeonQuantizedLstmWorkload.hpp"
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +010047#include "workloads/NeonResizeWorkload.hpp"
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +010048#include "workloads/NeonRsqrtWorkload.hpp"
josh minor036f02d2019-11-15 14:53:22 -060049#include "workloads/NeonSliceWorkload.hpp"
David Beck0dbe0ee2018-09-24 15:59:27 +010050#include "workloads/NeonSoftmaxBaseWorkload.hpp"
Ellen Norris-Thompson29794572019-06-26 16:40:36 +010051#include "workloads/NeonSpaceToDepthWorkload.hpp"
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +010052#include "workloads/NeonSplitterWorkload.hpp"
Matthew Jackson87f65ea2019-08-01 10:01:34 +010053#include "workloads/NeonStackWorkload.hpp"
FinnWilliamsArm1fa19192019-08-02 17:26:31 +010054#include "workloads/NeonStridedSliceWorkload.hpp"
Conor Kennedyb99480b2019-03-08 08:24:41 +000055#include "workloads/NeonSubtractionWorkload.hpp"
Sadik Armagan581742d2019-08-12 14:11:37 +010056#include "workloads/NeonTransposeConvolution2dWorkload.hpp"
telsoa014fcda012018-03-09 14:13:49 +000057#endif
58
59using namespace boost;
60
61namespace armnn
62{
telsoa014fcda012018-03-09 14:13:49 +000063
Aron Virginas-Tarfc824312018-10-15 15:00:13 +010064namespace
arovir017ff76c52018-10-09 09:40:58 +010065{
telsoa014fcda012018-03-09 14:13:49 +000066
arovir01085f0a42018-10-08 14:48:19 +010067bool IsNeonBackendSupported(Optional<std::string&> reasonIfUnsupported)
telsoa014fcda012018-03-09 14:13:49 +000068{
Matteo Martincighd95e9062019-01-31 15:35:59 +000069#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000070 return true;
71#else
Derek Lamberti0790dce2019-04-15 18:37:35 +010072 SetValueChecked(reasonIfUnsupported, "The armnn library has been built without NEON support");
telsoa014fcda012018-03-09 14:13:49 +000073 return false;
74#endif
75}
76
telsoa01c577f2c2018-08-31 09:22:23 +010077template<typename FloatFunc, typename Uint8Func, typename ... Params>
arovir01085f0a42018-10-08 14:48:19 +010078bool IsSupportedForDataTypeNeon(Optional<std::string&> reasonIfUnsupported,
telsoa014fcda012018-03-09 14:13:49 +000079 DataType dataType,
telsoa01c577f2c2018-08-31 09:22:23 +010080 FloatFunc floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000081 Uint8Func uint8FuncPtr,
82 Params&&... params)
83{
84 return IsNeonBackendSupported(reasonIfUnsupported) &&
85 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
86 dataType,
87 floatFuncPtr,
telsoa01c577f2c2018-08-31 09:22:23 +010088 floatFuncPtr,
telsoa014fcda012018-03-09 14:13:49 +000089 uint8FuncPtr,
narpra01db2b1602019-01-23 15:23:11 +000090 &FalseFunc<>,
kevmay012b4d88e2019-01-24 14:05:09 +000091 &FalseFunc<>,
telsoa014fcda012018-03-09 14:13:49 +000092 std::forward<Params>(params)...);
93}
94
Matteo Martincighd95e9062019-01-31 15:35:59 +000095#if defined(ARMCOMPUTENEON_ENABLED)
telsoa014fcda012018-03-09 14:13:49 +000096template<class FuncType, class... Args>
arovir01085f0a42018-10-08 14:48:19 +010097inline bool IsWorkloadSupported(FuncType& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
telsoa014fcda012018-03-09 14:13:49 +000098{
99 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
100 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
101 if (!supported && reasonIfUnsupported)
102 {
arovir01085f0a42018-10-08 14:48:19 +0100103 reasonIfUnsupported.value() = aclStatus.error_description();
telsoa014fcda012018-03-09 14:13:49 +0000104 }
105 return supported;
106}
107
108#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
109 return IsWorkloadSupported(func, reasonIfUnsupported, __VA_ARGS__);
110#else
111#define FORWARD_WORKLOAD_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
112 return IsNeonBackendSupported(reasonIfUnsupported);
113#endif
114
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100115} // anonymous namespace
116
Aron Virginas-Tar914e4db2019-09-09 13:36:45 +0100117bool NeonLayerSupport::IsAbsSupported(const TensorInfo& input,
118 const TensorInfo& output,
119 Optional<std::string&> reasonIfUnsupported) const
120{
121 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAbsWorkloadValidate,
122 reasonIfUnsupported,
123 input,
124 output);
125}
126
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100127bool NeonLayerSupport::IsActivationSupported(const TensorInfo& input,
128 const TensorInfo& output,
129 const ActivationDescriptor& descriptor,
130 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000131{
132 ignore_unused(descriptor);
telsoa01c577f2c2018-08-31 09:22:23 +0100133 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonActivationWorkloadValidate,
134 reasonIfUnsupported,
135 input,
136 output,
137 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000138}
139
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100140bool NeonLayerSupport::IsAdditionSupported(const TensorInfo& input0,
141 const TensorInfo& input1,
142 const TensorInfo& output,
143 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000144{
telsoa01c577f2c2018-08-31 09:22:23 +0100145 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonAdditionWorkloadValidate,
146 reasonIfUnsupported,
147 input0,
148 input1,
149 output);
telsoa014fcda012018-03-09 14:13:49 +0000150}
151
James Conroyd47a0642019-09-17 14:22:06 +0100152bool NeonLayerSupport::IsArgMinMaxSupported(const TensorInfo& input,
153 const TensorInfo& output,
154 const ArgMinMaxDescriptor& descriptor,
155 Optional<std::string&> reasonIfUnsupported) const
156{
157 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonArgMinMaxWorkloadValidate,
158 reasonIfUnsupported,
159 input,
160 output,
161 descriptor);
162}
163
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100164bool NeonLayerSupport::IsBatchNormalizationSupported(const TensorInfo& input,
165 const TensorInfo& output,
166 const TensorInfo& mean,
167 const TensorInfo& var,
168 const TensorInfo& beta,
169 const TensorInfo& gamma,
170 const BatchNormalizationDescriptor& descriptor,
171 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000172{
telsoa01c577f2c2018-08-31 09:22:23 +0100173 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonBatchNormalizationValidate,
174 reasonIfUnsupported,
175 input,
176 output,
177 mean,
178 var,
179 beta,
180 gamma,
181 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000182}
183
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100184bool NeonLayerSupport::IsComparisonSupported(const TensorInfo& input0,
185 const TensorInfo& input1,
186 const TensorInfo& output,
187 const ComparisonDescriptor& descriptor,
188 Optional<std::string&> reasonIfUnsupported) const
189{
190 if (descriptor.m_Operation == ComparisonOperation::Greater)
191 {
192 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGreaterWorkloadValidate,
193 reasonIfUnsupported,
194 input0,
195 input1,
196 output);
197 }
198
199 return false;
200}
201
Jim Flynn906f9462019-05-10 13:55:21 +0100202bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
203 const TensorInfo& output,
Jim Flynne242f2d2019-05-22 14:24:13 +0100204 const ConcatDescriptor& descriptor,
Jim Flynn906f9462019-05-10 13:55:21 +0100205 Optional<std::string&> reasonIfUnsupported) const
206{
Jim Flynne242f2d2019-05-22 14:24:13 +0100207 if (descriptor.GetNumDimensions() <= descriptor.GetConcatAxis())
208 {
209 SetValueChecked(reasonIfUnsupported, "Neon Concat: Concat axis > Number of dimensions.");
210 return false;
211 }
212
213 unsigned int concatInnerAxis = (descriptor.GetNumDimensions() - descriptor.GetConcatAxis()) - 1;
214 if(concatInnerAxis < 3) // Width, height, or channels
215 {
216 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConcatWorkloadValidate,
217 reasonIfUnsupported,
218 inputs,
219 output,
220 descriptor);
221 }
222 else if (concatInnerAxis == 3)
223 {
224 for (auto& input : inputs)
225 {
226 if (input && !output.IsTypeSpaceMatch(*input)) // Cannot use sub-tensors if the types are not same space
227 {
228 SetValueChecked(reasonIfUnsupported, "Neon Concat: Types and quantization parameters must match.");
229 return false;
230 }
231 }
232 return true; // Sub-tensors support concat along batch
233 }
234 else // > 4 dimensions not supported.
235 {
236 SetValueChecked(reasonIfUnsupported, "Neon Concat: Maximum of 4 dimensions supported.");
237 return false;
238 }
Jim Flynn906f9462019-05-10 13:55:21 +0100239}
240
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100241bool NeonLayerSupport::IsConstantSupported(const TensorInfo& output,
242 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000243{
244 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
245 output.GetDataType(),
246 &TrueFunc<>,
247 &TrueFunc<>);
248}
249
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100250bool NeonLayerSupport::IsConvertFp16ToFp32Supported(const TensorInfo& input,
251 const TensorInfo& output,
252 Optional<std::string&> reasonIfUnsupported) const
253{
254 ignore_unused(input);
255 ignore_unused(output);
256 ignore_unused(reasonIfUnsupported);
257 return true;
258}
259
260bool NeonLayerSupport::IsConvertFp32ToFp16Supported(const TensorInfo& input,
261 const TensorInfo& output,
262 Optional<std::string&> reasonIfUnsupported) const
263{
264 ignore_unused(input);
265 ignore_unused(output);
266 ignore_unused(reasonIfUnsupported);
267 return true;
268}
269
270bool NeonLayerSupport::IsConvolution2dSupported(const TensorInfo& input,
271 const TensorInfo& output,
272 const Convolution2dDescriptor& descriptor,
273 const TensorInfo& weights,
274 const Optional<TensorInfo>& biases,
275 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000276{
Aron Virginas-Tar07f25e02019-11-07 15:19:52 +0000277 if (weights.HasPerAxisQuantization())
278 {
279 return false;
280 }
281
surmeh013537c2c2018-05-18 16:31:43 +0100282 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonConvolution2dWorkloadValidate,
283 reasonIfUnsupported,
284 input,
285 output,
286 descriptor,
287 weights,
288 biases);
telsoa014fcda012018-03-09 14:13:49 +0000289}
290
Aron Virginas-Tar2f00b742019-09-30 13:28:08 +0100291bool NeonLayerSupport::IsDepthToSpaceSupported(const TensorInfo& input,
292 const TensorInfo& output,
293 const DepthToSpaceDescriptor& descriptor,
294 Optional<std::string&> reasonIfUnsupported) const
295{
296 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthToSpaceWorkloadValidate,
297 reasonIfUnsupported,
298 input,
299 output,
300 descriptor);
301}
302
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100303bool NeonLayerSupport::IsDepthwiseConvolutionSupported(const TensorInfo& input,
304 const TensorInfo& output,
305 const DepthwiseConvolution2dDescriptor& descriptor,
306 const TensorInfo& weights,
307 const Optional<TensorInfo>& biases,
308 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000309{
Aron Virginas-Tar5716de22019-11-15 10:22:28 +0000310 if (weights.HasPerAxisQuantization())
311 {
312 return false;
313 }
314
telsoa01c577f2c2018-08-31 09:22:23 +0100315 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
316 reasonIfUnsupported,
317 input,
318 output,
319 descriptor,
320 weights,
321 biases);
telsoa014fcda012018-03-09 14:13:49 +0000322}
323
Narumol Prangnawarat01961a72019-05-30 16:47:12 +0100324bool NeonLayerSupport::IsDequantizeSupported(const TensorInfo& input,
325 const TensorInfo& output,
326 Optional<std::string&> reasonIfUnsupported) const
327{
328 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDequantizeWorkloadValidate,
329 reasonIfUnsupported,
330 input,
331 output);
332}
333
Pablo Tellof0bd6832019-04-26 17:58:13 +0100334bool NeonLayerSupport::IsDilatedDepthwiseConvolutionSupported(const TensorInfo& input,
335 const TensorInfo& output,
336 const DepthwiseConvolution2dDescriptor& descriptor,
337 const TensorInfo& weights,
338 const Optional<TensorInfo>& biases,
339 Optional<std::string&> reasonIfUnsupported) const
340{
341 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonDepthwiseConvolutionWorkloadValidate,
342 reasonIfUnsupported,
343 input,
344 output,
345 descriptor,
346 weights,
347 biases);
348}
349
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100350bool NeonLayerSupport::IsFloorSupported(const TensorInfo& input,
351 const TensorInfo& output,
352 Optional<std::string&> reasonIfUnsupported) const
353{
354 ignore_unused(output);
355 return IsNeonBackendSupported(reasonIfUnsupported) &&
356 IsSupportedForDataTypeGeneric(reasonIfUnsupported,
357 input.GetDataType(),
358 &FalseFuncF16<>,
359 &TrueFunc<>,
narpra01db2b1602019-01-23 15:23:11 +0000360 &FalseFuncU8<>,
kevmay012b4d88e2019-01-24 14:05:09 +0000361 &FalseFuncI32<>,
362 &FalseFuncU8<>);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100363}
364
365bool NeonLayerSupport::IsFullyConnectedSupported(const TensorInfo& input,
366 const TensorInfo& output,
367 const TensorInfo& weights,
368 const TensorInfo& biases,
369 const FullyConnectedDescriptor& descriptor,
370 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000371{
telsoa01c577f2c2018-08-31 09:22:23 +0100372 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonFullyConnectedWorkloadValidate,
373 reasonIfUnsupported,
374 input,
375 output,
376 weights,
377 biases,
378 descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000379}
380
kevmay01eed85922019-01-28 08:37:25 +0000381bool NeonLayerSupport::IsGreaterSupported(const armnn::TensorInfo& input0,
382 const armnn::TensorInfo& input1,
383 const armnn::TensorInfo& output,
384 armnn::Optional<std::string&> reasonIfUnsupported) const
385{
Aron Virginas-Tar77bfb5e2019-10-16 17:45:38 +0100386 ComparisonDescriptor descriptor(ComparisonOperation::Greater);
387 return IsComparisonSupported(input0, input1, output, descriptor, reasonIfUnsupported);
kevmay01eed85922019-01-28 08:37:25 +0000388}
389
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100390bool NeonLayerSupport::IsInputSupported(const TensorInfo& input,
391 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000392{
Francis Murtaghb3fc2522019-08-09 13:20:50 +0100393 return IsNeonBackendSupported(reasonIfUnsupported);
telsoa014fcda012018-03-09 14:13:49 +0000394}
395
Sadik Armagan0d4863d2019-10-09 14:26:32 +0100396bool NeonLayerSupport::IsInstanceNormalizationSupported(const TensorInfo& input,
397 const TensorInfo& output,
398 const InstanceNormalizationDescriptor& descriptor,
399 Optional<std::string&> reasonIfUnsupported) const
400{
401 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonInstanceNormalizationWorkloadValidate,
402 reasonIfUnsupported,
403 input,
404 output,
405 descriptor);
406}
407
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100408bool NeonLayerSupport::IsL2NormalizationSupported(const TensorInfo& input,
409 const TensorInfo& output,
410 const L2NormalizationDescriptor& descriptor,
411 Optional<std::string&> reasonIfUnsupported) const
telsoa014fcda012018-03-09 14:13:49 +0000412{
Matteo Martincighbcd3c852018-09-28 14:14:12 +0100413 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonL2NormalizationWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000414}
415
Jan Eilersad5293a2019-07-08 09:57:55 +0100416bool NeonLayerSupport::IsLstmSupported(const TensorInfo& input,
417 const TensorInfo& outputStateIn,
418 const TensorInfo& cellStateIn,
419 const TensorInfo& scratchBuffer,
420 const TensorInfo& outputStateOut,
421 const TensorInfo& cellStateOut,
422 const TensorInfo& output,
423 const LstmDescriptor& descriptor,
424 const LstmInputParamsInfo& paramsInfo,
425 Optional<std::string&> reasonIfUnsupported) const
426{
427 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonLstmFloatWorkloadValidate,
428 reasonIfUnsupported,
429 input,
430 outputStateIn,
431 cellStateIn,
432 scratchBuffer,
433 outputStateOut,
434 cellStateOut,
435 output,
436 descriptor,
437 paramsInfo);
438}
439
Nattapat Chaimanowong4e6597a2018-12-20 14:14:06 +0000440bool NeonLayerSupport::IsMaximumSupported(const TensorInfo& input0,
441 const TensorInfo& input1,
442 const TensorInfo& output,
443 Optional<std::string&> reasonIfUnsupported) const
444{
445 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMaximumWorkloadValidate,
446 reasonIfUnsupported,
447 input0,
448 input1,
449 output);
450}
451
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100452bool NeonLayerSupport::IsMeanSupported(const TensorInfo& input,
453 const TensorInfo& output,
454 const MeanDescriptor& descriptor,
455 Optional<std::string&> reasonIfUnsupported) const
narpra0132b90462018-09-13 11:07:48 +0100456{
Matthew Benthamfd899962018-12-31 15:49:42 +0000457 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMeanWorkloadValidate,
458 reasonIfUnsupported,
459 input,
460 output,
461 descriptor);
narpra0132b90462018-09-13 11:07:48 +0100462}
463
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100464bool NeonLayerSupport::IsMergerSupported(const std::vector<const TensorInfo*> inputs,
Nikhil Raj8599a412018-11-19 14:51:07 +0000465 const TensorInfo& output,
Jim Flynne242f2d2019-05-22 14:24:13 +0100466 const MergerDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100467 Optional<std::string&> reasonIfUnsupported) const
468{
Jim Flynne242f2d2019-05-22 14:24:13 +0100469 return IsConcatSupported(inputs, output, descriptor, reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100470}
471
Conor Kennedy54b21692019-01-09 07:57:38 +0000472bool NeonLayerSupport::IsMinimumSupported(const TensorInfo& input0,
473 const TensorInfo& input1,
474 const TensorInfo& output,
475 Optional<std::string&> reasonIfUnsupported) const
476{
477 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMinimumWorkloadValidate,
478 reasonIfUnsupported,
479 input0,
480 input1,
481 output);
482}
483
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100484bool NeonLayerSupport::IsMultiplicationSupported(const TensorInfo& input0,
485 const TensorInfo& input1,
486 const TensorInfo& output,
487 Optional<std::string&> reasonIfUnsupported) const
488{
489 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonMultiplicationWorkloadValidate,
490 reasonIfUnsupported,
491 input0,
492 input1,
493 output);
494}
495
496bool NeonLayerSupport::IsNormalizationSupported(const TensorInfo& input,
497 const TensorInfo& output,
498 const NormalizationDescriptor& descriptor,
499 Optional<std::string&> reasonIfUnsupported) const
500{
501 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonNormalizationWorkloadValidate,
502 reasonIfUnsupported,
503 input,
504 output,
505 descriptor);
506}
507
508bool NeonLayerSupport::IsOutputSupported(const TensorInfo& output,
509 Optional<std::string&> reasonIfUnsupported) const
510{
Francis Murtaghb3fc2522019-08-09 13:20:50 +0100511 return IsNeonBackendSupported(reasonIfUnsupported);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100512}
513
Éanna Ó Catháin12055742019-01-25 10:01:40 +0000514bool NeonLayerSupport::IsPadSupported(const TensorInfo& input,
515 const TensorInfo& output,
516 const PadDescriptor& descriptor,
517 Optional<std::string&> reasonIfUnsupported) const
518{
519 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPadWorkloadValidate,
520 reasonIfUnsupported,
521 input,
522 output,
523 descriptor);
524}
525
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100526bool NeonLayerSupport::IsPermuteSupported(const TensorInfo& input,
527 const TensorInfo& output,
528 const PermuteDescriptor& descriptor,
529 Optional<std::string&> reasonIfUnsupported) const
530{
531 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPermuteWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
telsoa014fcda012018-03-09 14:13:49 +0000532}
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100533
534bool NeonLayerSupport::IsPooling2dSupported(const TensorInfo& input,
535 const TensorInfo& output,
536 const Pooling2dDescriptor& descriptor,
537 Optional<std::string&> reasonIfUnsupported) const
538{
539 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPooling2dWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
540}
541
Nikhil Raj9b461482019-07-03 15:58:31 +0100542bool NeonLayerSupport::IsPreluSupported(const armnn::TensorInfo &input,
543 const armnn::TensorInfo &alpha,
544 const armnn::TensorInfo &output,
545 armnn::Optional<std::string &> reasonIfUnsupported) const
546{
547 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonPreluWorkloadValidate, reasonIfUnsupported, input, alpha, output);
548}
549
Sadik Armaganfabc2892019-05-31 09:05:11 +0100550bool NeonLayerSupport::IsQuantizeSupported(const TensorInfo& input,
551 const TensorInfo& output,
552 Optional<std::string&> reasonIfUnsupported) const
553{
554 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizeWorkloadValidate,
555 reasonIfUnsupported,
556 input,
557 output);
558}
559
Francis Murtagh4fc3c482019-08-02 13:20:54 +0100560bool NeonLayerSupport::IsQuantizedLstmSupported(const TensorInfo& input,
561 const TensorInfo& cellStateIn,
562 const TensorInfo& outputStateIn,
563 const TensorInfo& cellStateOut,
564 const TensorInfo& outputStateOut,
565 const QuantizedLstmInputParamsInfo& paramsInfo,
566 Optional<std::string&> reasonIfUnsupported) const
567{
568 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonQuantizedLstmWorkloadValidate,
569 reasonIfUnsupported,
570 input,
571 cellStateIn,
572 outputStateIn,
573 cellStateOut,
574 outputStateOut,
575 paramsInfo);
576}
577
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100578bool NeonLayerSupport::IsReshapeSupported(const TensorInfo& input,
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000579 const ReshapeDescriptor& descriptor,
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100580 Optional<std::string&> reasonIfUnsupported) const
581{
Matteo Martincigh992d6dc2019-01-10 17:34:20 +0000582 ignore_unused(descriptor);
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100583 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
584 input.GetDataType(),
585 &TrueFunc<>,
586 &TrueFunc<>);
587}
588
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +0100589bool NeonLayerSupport::IsResizeSupported(const TensorInfo& input,
590 const TensorInfo& output,
591 const ResizeDescriptor& descriptor,
592 Optional<std::string&> reasonIfUnsupported) const
593{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +0100594 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonResizeWorkloadValidate,
595 reasonIfUnsupported,
596 input,
597 output,
598 descriptor);
Aron Virginas-Tar169d2f12019-07-01 19:01:44 +0100599}
600
Sadik Armaganc625f002018-12-17 11:32:16 +0000601bool NeonLayerSupport::IsResizeBilinearSupported(const TensorInfo& input,
602 const TensorInfo& output,
603 Optional<std::string&> reasonIfUnsupported) const
604{
Ellen Norris-Thompson37e68682019-07-15 14:23:30 +0100605 ResizeDescriptor descriptor;
606 descriptor.m_Method = ResizeMethod::Bilinear;
607 descriptor.m_DataLayout = DataLayout::NCHW;
608
609 const TensorShape& outputShape = output.GetShape();
610 descriptor.m_TargetHeight = outputShape[2];
611 descriptor.m_TargetWidth = outputShape[3];
612
613 return IsResizeSupported(input, output, descriptor, reasonIfUnsupported);
Sadik Armaganc625f002018-12-17 11:32:16 +0000614}
615
Aron Virginas-Tar0dd3b432019-09-10 13:55:09 +0100616bool NeonLayerSupport::IsRsqrtSupported(const TensorInfo& input,
617 const TensorInfo& output,
618 Optional<std::string&> reasonIfUnsupported) const
619{
620 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonRsqrtWorkloadValidate, reasonIfUnsupported, input, output);
621}
622
josh minor036f02d2019-11-15 14:53:22 -0600623bool NeonLayerSupport::IsSliceSupported(const TensorInfo& input,
624 const TensorInfo& output,
625 const SliceDescriptor& descriptor,
626 Optional<std::string&> reasonIfUnsupported) const
627{
628 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSliceWorkloadValidate,
629 reasonIfUnsupported,
630 input,
631 output,
632 descriptor);
633}
634
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100635bool NeonLayerSupport::IsSoftmaxSupported(const TensorInfo& input,
636 const TensorInfo& output,
637 const SoftmaxDescriptor& descriptor,
638 Optional<std::string&> reasonIfUnsupported) const
639{
640 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSoftmaxWorkloadValidate, reasonIfUnsupported, input, output, descriptor);
641}
642
Ellen Norris-Thompson29794572019-06-26 16:40:36 +0100643bool NeonLayerSupport::IsSpaceToDepthSupported(const TensorInfo& input,
644 const TensorInfo& output,
645 const SpaceToDepthDescriptor& descriptor,
646 Optional<std::string&> reasonIfUnsupported) const
647{
648 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSpaceToDepthWorkloadValidate,
649 reasonIfUnsupported,
650 input,
651 output,
652 descriptor);
653}
654
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100655bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
656 const ViewsDescriptor& descriptor,
657 Optional<std::string&> reasonIfUnsupported) const
658{
659 ignore_unused(descriptor);
660 return IsSupportedForDataTypeNeon(reasonIfUnsupported,
661 input.GetDataType(),
662 &TrueFunc<>,
663 &TrueFunc<>);
664}
665
Narumol Prangnawarat15eb5832019-05-20 15:31:05 +0100666bool NeonLayerSupport::IsSplitterSupported(const TensorInfo& input,
667 const std::vector<std::reference_wrapper<TensorInfo>>& outputs,
668 const ViewsDescriptor& descriptor,
669 Optional<std::string&> reasonIfUnsupported) const
670{
671#if defined(ARMCOMPUTENEON_ENABLED)
672 // Split along the last dimension, cannot use sub-tensors
673 // as width and height of the sub-tensors do not match
674 // the width and height of the parent tensor
675 // in case of input with more than 2D.
676 std::set<unsigned int> splitAxis = ComputeSplitAxis(descriptor, input.GetShape());
677 if (descriptor.GetNumDimensions() > 2 && splitAxis.size() == 1 &&
678 *splitAxis.begin() == descriptor.GetNumDimensions() - 1 )
679 {
680 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSplitterWorkloadValidate,
681 reasonIfUnsupported,
682 input,
683 outputs,
684 *splitAxis.begin());
685 }
686#endif
687 for (auto output : outputs)
688 {
689 if (!input.IsTypeSpaceMatch(output)) // Cannot use sub-tensors if the types are not same space
690 {
691 SetValueChecked(reasonIfUnsupported, "Neon Splitter: Types and quantization parameters must match.");
692 return false;
693 }
694 }
695 return true;
696}
697
Matthew Jackson87f65ea2019-08-01 10:01:34 +0100698bool NeonLayerSupport::IsStackSupported(const std::vector<const TensorInfo*>& inputs,
699 const TensorInfo& output,
700 const StackDescriptor& descriptor,
701 Optional<std::string&> reasonIfUnsupported) const
702{
703 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStackWorkloadValidate,
704 reasonIfUnsupported,
705 inputs,
706 output,
707 descriptor);
708}
709
FinnWilliamsArm1fa19192019-08-02 17:26:31 +0100710bool NeonLayerSupport::IsStridedSliceSupported(const TensorInfo& input,
711 const TensorInfo& output,
712 const StridedSliceDescriptor& descriptor,
713 Optional<std::string&> reasonIfUnsupported) const
714{
715 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonStridedSliceWorkloadValidate,
716 reasonIfUnsupported,
717 input,
718 output,
719 descriptor);
720}
721
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100722bool NeonLayerSupport::IsSubtractionSupported(const TensorInfo& input0,
723 const TensorInfo& input1,
724 const TensorInfo& output,
725 Optional<std::string&> reasonIfUnsupported) const
726{
727 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonSubtractionWorkloadValidate,
728 reasonIfUnsupported,
729 input0,
730 input1,
731 output);
732}
733
Sadik Armagan581742d2019-08-12 14:11:37 +0100734bool NeonLayerSupport::IsTransposeConvolution2dSupported(const TensorInfo& input,
735 const TensorInfo& output,
736 const TransposeConvolution2dDescriptor& descriptor,
737 const TensorInfo& weights,
738 const Optional<TensorInfo>& biases,
739 Optional<std::string&> reasonIfUnsupported) const
740{
741 FORWARD_WORKLOAD_VALIDATE_FUNC(NeonTransposeConvolution2dWorkloadValidate,
742 reasonIfUnsupported,
743 input,
744 output,
745 descriptor,
746 weights,
747 biases);
748}
749
Aron Virginas-Tarfc824312018-10-15 15:00:13 +0100750} // namespace armnn