IVGCVSW-3250 Extend the Gather workload for QSymm16 support

 * Add LayerTests and EndToEndTests for QSymm16
 * Updated GatherQueueDescriptor::Validate function
 * Reimplemented RefLayerSupport::IsGatherSupported

Signed-off-by: Ellen Norris-Thompson <ellen.norris-thompson@arm.com>
Change-Id: I5b4df55d31b5ee3c5563d2df17b412a387c27595
diff --git a/src/backends/backendsCommon/WorkloadData.cpp b/src/backends/backendsCommon/WorkloadData.cpp
index 5ca4928..cd40097 100644
--- a/src/backends/backendsCommon/WorkloadData.cpp
+++ b/src/backends/backendsCommon/WorkloadData.cpp
@@ -1597,23 +1597,41 @@
 
 void GatherQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
 {
-    ValidateNumInputs(workloadInfo, "GatherQueueDescriptor", 2);
-    ValidateNumOutputs(workloadInfo, "GatherQueueDescriptor", 1);
+    const std::string GatherQueueDescriptorStr = "GatherQueueDescriptor";
+
+    ValidateNumInputs(workloadInfo, GatherQueueDescriptorStr, 2);
+    ValidateNumOutputs(workloadInfo, GatherQueueDescriptorStr, 1);
 
     const TensorInfo& indices = workloadInfo.m_InputTensorInfos[1];
 
     if (indices.GetDataType() != DataType::Signed32)
     {
-        throw InvalidArgumentException("GatherQueueDescriptor: Indices tensor type must be int32.");
+        throw InvalidArgumentException(GatherQueueDescriptorStr + ": Indices tensor type must be int32.");
     }
 
+    std::vector<DataType> supportedTypes =
+    {
+            DataType::Float16,
+            DataType::Float32,
+            DataType::QuantisedAsymm8,
+            DataType::QuantisedSymm16
+    };
+
+    ValidateDataTypes(workloadInfo.m_InputTensorInfos[0],
+                      supportedTypes,
+                      GatherQueueDescriptorStr);
+
+    ValidateTensorDataTypesMatch(workloadInfo.m_InputTensorInfos[0],
+                      workloadInfo.m_OutputTensorInfos[0],
+                      GatherQueueDescriptorStr, "Input", "Output");
+
     const TensorInfo& params = workloadInfo.m_InputTensorInfos[0];
     const TensorInfo& output = workloadInfo.m_OutputTensorInfos[0];
     unsigned int paramsDim = params.GetNumDimensions();
     unsigned int indicesDim = indices.GetNumDimensions();
     unsigned int outputDim = paramsDim - 1 + indicesDim;
 
-    ValidateTensorNumDimensions(output, "GatherQueueDescriptor", outputDim, "output");
+    ValidateTensorNumDimensions(output, GatherQueueDescriptorStr, outputDim, "output");
 }
 
 void DetectionPostProcessQueueDescriptor::Validate(const WorkloadInfo& workloadInfo) const
diff --git a/src/backends/backendsCommon/WorkloadFactory.cpp b/src/backends/backendsCommon/WorkloadFactory.cpp
index 2fba3b7..7cda3fe 100644
--- a/src/backends/backendsCommon/WorkloadFactory.cpp
+++ b/src/backends/backendsCommon/WorkloadFactory.cpp
@@ -323,7 +323,7 @@
             const TensorInfo& input1 = layer.GetInputSlot(1).GetConnection()->GetTensorInfo();
             const TensorInfo& output = layer.GetOutputSlot(0).GetTensorInfo();
             result = layerSupportObject->IsGatherSupported(OverrideDataType(input0, dataType),
-                                                           OverrideDataType(input1, dataType),
+                                                           input1,
                                                            OverrideDataType(output, dataType),
                                                            reason);
             break;
diff --git a/src/backends/backendsCommon/test/LayerTests.cpp b/src/backends/backendsCommon/test/LayerTests.cpp
index 64b9676..a625097 100644
--- a/src/backends/backendsCommon/test/LayerTests.cpp
+++ b/src/backends/backendsCommon/test/LayerTests.cpp
@@ -9551,6 +9551,13 @@
     return Gather1DParamsTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
 }
 
+LayerTestResult<int16_t, 1> Gather1DParamsInt16Test(
+        armnn::IWorkloadFactory& workloadFactory,
+        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    return Gather1DParamsTestImpl<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager);
+}
+
 LayerTestResult<float, 2> GatherMultiDimParamsFloatTest(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
@@ -9565,6 +9572,13 @@
     return GatherMultiDimParamsTestImpl<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager);
 }
 
+LayerTestResult<int16_t, 2> GatherMultiDimParamsInt16Test(
+        armnn::IWorkloadFactory& workloadFactory,
+        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    return GatherMultiDimParamsTestImpl<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager);
+}
+
 LayerTestResult<float, 4> GatherMultiDimParamsMultiDimIndicesFloatTest(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
@@ -9580,6 +9594,14 @@
         workloadFactory, memoryManager);
 }
 
+LayerTestResult<int16_t, 4> GatherMultiDimParamsMultiDimIndicesInt16Test(
+        armnn::IWorkloadFactory& workloadFactory,
+        const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
+{
+    return GatherMultiDimParamsMultiDimIndicesTestImpl<armnn::DataType::QuantisedSymm16>(
+            workloadFactory, memoryManager);
+}
+
 LayerTestResult<float, 4> DequantizeSimpleUint8Test(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
diff --git a/src/backends/backendsCommon/test/LayerTests.hpp b/src/backends/backendsCommon/test/LayerTests.hpp
index 77adca1..d54d41e 100644
--- a/src/backends/backendsCommon/test/LayerTests.hpp
+++ b/src/backends/backendsCommon/test/LayerTests.hpp
@@ -1909,6 +1909,10 @@
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
 
+LayerTestResult<int16_t, 1> Gather1DParamsInt16Test(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
 LayerTestResult<float, 2> GatherMultiDimParamsFloatTest(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
@@ -1917,6 +1921,10 @@
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
 
+LayerTestResult<int16_t, 2> GatherMultiDimParamsInt16Test(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
 LayerTestResult<float, 4> GatherMultiDimParamsMultiDimIndicesFloatTest(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
@@ -1925,6 +1933,10 @@
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
 
+LayerTestResult<int16_t, 4> GatherMultiDimParamsMultiDimIndicesInt16Test(
+    armnn::IWorkloadFactory& workloadFactory,
+    const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
+
 LayerTestResult<float, 4> DequantizeSimpleUint8Test(
     armnn::IWorkloadFactory& workloadFactory,
     const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager);
diff --git a/src/backends/reference/RefLayerSupport.cpp b/src/backends/reference/RefLayerSupport.cpp
index a180781..4e9a678 100644
--- a/src/backends/reference/RefLayerSupport.cpp
+++ b/src/backends/reference/RefLayerSupport.cpp
@@ -130,6 +130,14 @@
     }
 };
 
+struct TypeIs : public Rule
+{
+    TypeIs(const TensorInfo& info, DataType dt)
+    {
+        m_Res = dt == info.GetDataType();
+    }
+};
+
 struct BiasAndWeightsTypesMatch : public Rule
 {
     BiasAndWeightsTypesMatch(const TensorInfo& biases, const TensorInfo& weights)
@@ -721,12 +729,27 @@
                                         const armnn::TensorInfo& output,
                                         armnn::Optional<std::string&> reasonIfUnsupported) const
 {
-    ignore_unused(input1);
-    ignore_unused(output);
-    return IsSupportedForDataTypeRef(reasonIfUnsupported,
-                                     input0.GetDataType(),
-                                     &TrueFunc<>,
-                                     &TrueFunc<>);
+    bool supported = true;
+    std::array<DataType,3> supportedTypes =
+    {
+            DataType::Float32,
+            DataType::QuantisedAsymm8,
+            DataType::QuantisedSymm16
+    };
+
+    supported &= CheckSupportRule(TypeAnyOf(input0, supportedTypes), reasonIfUnsupported,
+                                  "Reference Gather: input type not supported");
+
+    supported &= CheckSupportRule(TypeAnyOf(output, supportedTypes), reasonIfUnsupported,
+                                  "Reference Gather: output type not supported");
+
+    supported &= CheckSupportRule(TypeIs(input1, DataType::Signed32), reasonIfUnsupported,
+                                  "Reference Gather: indices (input1) type not supported");
+
+    supported &= CheckSupportRule(TypesAreEqual(input0, output), reasonIfUnsupported,
+                                  "Reference Gather: input and output types not matching");
+
+    return supported;
 }
 
 bool RefLayerSupport::IsGreaterSupported(const TensorInfo& input0,
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index be73116..c186c03 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -448,6 +448,11 @@
     GatherEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
 }
 
+BOOST_AUTO_TEST_CASE(RefGatherInt16Test)
+{
+    GatherEndToEnd<armnn::DataType::QuantisedSymm16>(defaultBackends);
+}
+
 BOOST_AUTO_TEST_CASE(RefGatherMultiDimFloatTest)
 {
     GatherMultiDimEndToEnd<armnn::DataType::Float32>(defaultBackends);
@@ -458,6 +463,11 @@
     GatherMultiDimEndToEnd<armnn::DataType::QuantisedAsymm8>(defaultBackends);
 }
 
+BOOST_AUTO_TEST_CASE(RefGatherMultiDimInt16Test)
+{
+    GatherMultiDimEndToEnd<armnn::DataType::QuantisedSymm16>(defaultBackends);
+}
+
 BOOST_AUTO_TEST_CASE(DequantizeEndToEndSimpleTest)
 {
     DequantizeEndToEndSimple<armnn::DataType::QuantisedAsymm8>(defaultBackends);
diff --git a/src/backends/reference/test/RefLayerTests.cpp b/src/backends/reference/test/RefLayerTests.cpp
index 4cb261f..f933bfe 100644
--- a/src/backends/reference/test/RefLayerTests.cpp
+++ b/src/backends/reference/test/RefLayerTests.cpp
@@ -896,10 +896,13 @@
 // Gather
 ARMNN_AUTO_TEST_CASE(Gather1DParamsFloat, Gather1DParamsFloatTest)
 ARMNN_AUTO_TEST_CASE(Gather1DParamsUint8, Gather1DParamsUint8Test)
+ARMNN_AUTO_TEST_CASE(Gather1DParamsInt16, Gather1DParamsInt16Test)
 ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsFloat, GatherMultiDimParamsFloatTest)
 ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsUint8, GatherMultiDimParamsUint8Test)
+ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsInt16, GatherMultiDimParamsInt16Test)
 ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsMultiDimIndicesFloat, GatherMultiDimParamsMultiDimIndicesFloatTest)
 ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsMultiDimIndicesUint8, GatherMultiDimParamsMultiDimIndicesUint8Test)
+ARMNN_AUTO_TEST_CASE(GatherMultiDimParamsMultiDimIndicesInt16, GatherMultiDimParamsMultiDimIndicesInt16Test)
 
 // Detection PostProcess
 BOOST_AUTO_TEST_CASE(DetectionPostProcessRegularNmsFloat)