IVGCVSW-4603 Support comparison operators in Neon

    * Deprecate NeonGreaterWorkload
    * Add NeonComparisonWorkload to encompass all comparison operators

Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com>
Change-Id: I5e828088d17e994fc5cb0b908719b53ee01fa959
diff --git a/src/backends/backendsCommon/WorkloadData.hpp b/src/backends/backendsCommon/WorkloadData.hpp
index ad71e3c..9239f4a 100644
--- a/src/backends/backendsCommon/WorkloadData.hpp
+++ b/src/backends/backendsCommon/WorkloadData.hpp
@@ -259,7 +259,7 @@
     void Validate(const WorkloadInfo& workloadInfo) const;
 };
 
-// Equal layer workload data
+// Deprecated use ComparisonQueueDescriptor instead
 struct EqualQueueDescriptor : QueueDescriptor
 {
     void Validate(const WorkloadInfo& workloadInfo) const;
diff --git a/src/backends/neon/NeonLayerSupport.cpp b/src/backends/neon/NeonLayerSupport.cpp
index 999b158..c01a178 100644
--- a/src/backends/neon/NeonLayerSupport.cpp
+++ b/src/backends/neon/NeonLayerSupport.cpp
@@ -24,11 +24,11 @@
 #include "workloads/NeonArgMinMaxWorkload.hpp"
 #include "workloads/NeonBatchNormalizationWorkload.hpp"
 #include "workloads/NeonBatchToSpaceNdWorkload.hpp"
+#include "workloads/NeonComparisonWorkload.hpp"
 #include "workloads/NeonConvolution2dWorkload.hpp"
 #include "workloads/NeonDepthToSpaceWorkload.hpp"
 #include "workloads/NeonDepthwiseConvolutionWorkload.hpp"
 #include "workloads/NeonDequantizeWorkload.hpp"
-#include "workloads/NeonGreaterWorkload.hpp"
 #include "workloads/NeonInstanceNormalizationWorkload.hpp"
 #include "workloads/NeonL2NormalizationFloatWorkload.hpp"
 #include "workloads/NeonLstmFloatWorkload.hpp"
@@ -202,16 +202,13 @@
                                              const ComparisonDescriptor& descriptor,
                                              Optional<std::string&> reasonIfUnsupported) const
 {
-    if (descriptor.m_Operation == ComparisonOperation::Greater)
-    {
-        FORWARD_WORKLOAD_VALIDATE_FUNC(NeonGreaterWorkloadValidate,
-                                       reasonIfUnsupported,
-                                       input0,
-                                       input1,
-                                       output);
-    }
 
-    return false;
+    FORWARD_WORKLOAD_VALIDATE_FUNC(NeonComparisonWorkloadValidate,
+                                   reasonIfUnsupported,
+                                   input0,
+                                   input1,
+                                   output,
+                                   descriptor);
 }
 
 bool NeonLayerSupport::IsConcatSupported(const std::vector<const TensorInfo*> inputs,
diff --git a/src/backends/neon/NeonWorkloadFactory.cpp b/src/backends/neon/NeonWorkloadFactory.cpp
index bf26d82..982104e 100644
--- a/src/backends/neon/NeonWorkloadFactory.cpp
+++ b/src/backends/neon/NeonWorkloadFactory.cpp
@@ -139,14 +139,7 @@
 std::unique_ptr<IWorkload> NeonWorkloadFactory::CreateComparison(const ComparisonQueueDescriptor& descriptor,
                                                                  const WorkloadInfo& info) const
 {
-    if (descriptor.m_Parameters.m_Operation == ComparisonOperation::Greater)
-    {
-        GreaterQueueDescriptor greaterQueueDescriptor;
-        greaterQueueDescriptor.m_Inputs  = descriptor.m_Inputs;
-        greaterQueueDescriptor.m_Outputs = descriptor.m_Outputs;
-        return std::make_unique<NeonGreaterWorkload>(greaterQueueDescriptor, info);
-    }
-    return MakeWorkloadHelper<NullWorkload, NullWorkload>(descriptor, info);
+    return std::make_unique<NeonComparisonWorkload>(descriptor, info);
 }
 
 std::unique_ptr<armnn::IWorkload> NeonWorkloadFactory::CreateConcat(const ConcatQueueDescriptor& descriptor,
diff --git a/src/backends/neon/backend.mk b/src/backends/neon/backend.mk
index 3cb8bd5..3b3333a 100644
--- a/src/backends/neon/backend.mk
+++ b/src/backends/neon/backend.mk
@@ -27,6 +27,7 @@
         workloads/NeonArgMinMaxWorkload.cpp \
         workloads/NeonBatchNormalizationWorkload.cpp \
         workloads/NeonBatchToSpaceNdWorkload.cpp \
+        workloads/NeonComparisonWorkload.cpp \
         workloads/NeonConcatWorkload.cpp \
         workloads/NeonConstantWorkload.cpp \
         workloads/NeonConvertFp16ToFp32Workload.cpp \
@@ -38,7 +39,6 @@
         workloads/NeonDetectionPostProcessWorkload.cpp \
         workloads/NeonFloorFloatWorkload.cpp \
         workloads/NeonFullyConnectedWorkload.cpp \
-        workloads/NeonGreaterWorkload.cpp \
         workloads/NeonInstanceNormalizationWorkload.cpp \
         workloads/NeonL2NormalizationFloatWorkload.cpp \
         workloads/NeonLstmFloatWorkload.cpp \
diff --git a/src/backends/neon/test/NeonLayerTests.cpp b/src/backends/neon/test/NeonLayerTests.cpp
index 06b5597..19a8916 100644
--- a/src/backends/neon/test/NeonLayerTests.cpp
+++ b/src/backends/neon/test/NeonLayerTests.cpp
@@ -623,6 +623,15 @@
 // Floor
 ARMNN_AUTO_TEST_CASE(SimpleFloor, SimpleFloorTest<DataType::Float32>)
 
+// Equal
+ARMNN_AUTO_TEST_CASE(EqualSimple,            EqualSimpleTest)
+ARMNN_AUTO_TEST_CASE(EqualBroadcast1Element, EqualBroadcast1ElementTest)
+ARMNN_AUTO_TEST_CASE(EqualBroadcast1dVector, EqualBroadcast1dVectorTest)
+
+ARMNN_AUTO_TEST_CASE(EqualSimpleUint8,            EqualSimpleUint8Test)
+ARMNN_AUTO_TEST_CASE(EqualBroadcast1ElementUint8, EqualBroadcast1ElementUint8Test)
+ARMNN_AUTO_TEST_CASE(EqualBroadcast1dVectorUint8, EqualBroadcast1dVectorUint8Test)
+
 // Greater
 ARMNN_AUTO_TEST_CASE(GreaterSimple,            GreaterSimpleTest)
 ARMNN_AUTO_TEST_CASE(GreaterBroadcast1Element, GreaterBroadcast1ElementTest)
@@ -632,6 +641,42 @@
 ARMNN_AUTO_TEST_CASE(GreaterBroadcast1ElementUint8, GreaterBroadcast1ElementUint8Test)
 ARMNN_AUTO_TEST_CASE(GreaterBroadcast1dVectorUint8, GreaterBroadcast1dVectorUint8Test)
 
+// GreaterOrEqual
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualSimple,            GreaterOrEqualSimpleTest)
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualBroadcast1Element, GreaterOrEqualBroadcast1ElementTest)
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualBroadcast1dVector, GreaterOrEqualBroadcast1dVectorTest)
+
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualSimpleUint8,            GreaterOrEqualSimpleUint8Test)
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualBroadcast1ElementUint8, GreaterOrEqualBroadcast1ElementUint8Test)
+ARMNN_AUTO_TEST_CASE(GreaterOrEqualBroadcast1dVectorUint8, GreaterOrEqualBroadcast1dVectorUint8Test)
+
+// Less
+ARMNN_AUTO_TEST_CASE(LessSimple,            LessSimpleTest)
+ARMNN_AUTO_TEST_CASE(LessBroadcast1Element, LessBroadcast1ElementTest)
+ARMNN_AUTO_TEST_CASE(LessBroadcast1dVector, LessBroadcast1dVectorTest)
+
+ARMNN_AUTO_TEST_CASE(LessSimpleUint8,            LessSimpleUint8Test)
+ARMNN_AUTO_TEST_CASE(LessBroadcast1ElementUint8, LessBroadcast1ElementUint8Test)
+ARMNN_AUTO_TEST_CASE(LessBroadcast1dVectorUint8, LessBroadcast1dVectorUint8Test)
+
+// LessOrEqual
+ARMNN_AUTO_TEST_CASE(LessOrEqualSimple,            LessOrEqualSimpleTest)
+ARMNN_AUTO_TEST_CASE(LessOrEqualBroadcast1Element, LessOrEqualBroadcast1ElementTest)
+ARMNN_AUTO_TEST_CASE(LessOrEqualBroadcast1dVector, LessOrEqualBroadcast1dVectorTest)
+
+ARMNN_AUTO_TEST_CASE(LessOrEqualSimpleUint8,            LessOrEqualSimpleUint8Test)
+ARMNN_AUTO_TEST_CASE(LessOrEqualBroadcast1ElementUint8, LessOrEqualBroadcast1ElementUint8Test)
+ARMNN_AUTO_TEST_CASE(LessOrEqualBroadcast1dVectorUint8, LessOrEqualBroadcast1dVectorUint8Test)
+
+// NotEqual
+ARMNN_AUTO_TEST_CASE(NotEqualSimple,            NotEqualSimpleTest)
+ARMNN_AUTO_TEST_CASE(NotEqualBroadcast1Element, NotEqualBroadcast1ElementTest)
+ARMNN_AUTO_TEST_CASE(NotEqualBroadcast1dVector, NotEqualBroadcast1dVectorTest)
+
+ARMNN_AUTO_TEST_CASE(NotEqualSimpleUint8,            NotEqualSimpleUint8Test)
+ARMNN_AUTO_TEST_CASE(NotEqualBroadcast1ElementUint8, NotEqualBroadcast1ElementUint8Test)
+ARMNN_AUTO_TEST_CASE(NotEqualBroadcast1dVectorUint8, NotEqualBroadcast1dVectorUint8Test)
+
 // Reshape
 ARMNN_AUTO_TEST_CASE(SimpleReshapeFloat32, SimpleReshapeTest<armnn::DataType::Float32>)
 ARMNN_AUTO_TEST_CASE(SimpleReshapeUint8, SimpleReshapeTest<armnn::DataType::QAsymmU8>)
diff --git a/src/backends/neon/workloads/CMakeLists.txt b/src/backends/neon/workloads/CMakeLists.txt
index 8160710..cbe1e3b 100644
--- a/src/backends/neon/workloads/CMakeLists.txt
+++ b/src/backends/neon/workloads/CMakeLists.txt
@@ -16,6 +16,8 @@
     NeonBatchNormalizationWorkload.hpp
     NeonBatchToSpaceNdWorkload.cpp
     NeonBatchToSpaceNdWorkload.hpp
+    NeonComparisonWorkload.cpp
+    NeonComparisonWorkload.hpp
     NeonConcatWorkload.cpp
     NeonConcatWorkload.hpp
     NeonConstantWorkload.cpp
@@ -38,8 +40,6 @@
     NeonFloorFloatWorkload.hpp
     NeonFullyConnectedWorkload.cpp
     NeonFullyConnectedWorkload.hpp
-    NeonGreaterWorkload.cpp
-    NeonGreaterWorkload.hpp
     NeonInstanceNormalizationWorkload.cpp
     NeonInstanceNormalizationWorkload.hpp
     NeonL2NormalizationFloatWorkload.cpp
diff --git a/src/backends/neon/workloads/NeonComparisonWorkload.cpp b/src/backends/neon/workloads/NeonComparisonWorkload.cpp
new file mode 100644
index 0000000..0edb332
--- /dev/null
+++ b/src/backends/neon/workloads/NeonComparisonWorkload.cpp
@@ -0,0 +1,53 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "NeonComparisonWorkload.hpp"
+#include <aclCommon/ArmComputeUtils.hpp>
+#include <aclCommon/ArmComputeTensorUtils.hpp>
+#include <backendsCommon/CpuTensorHandle.hpp>
+
+namespace armnn
+{
+using namespace armcomputetensorutils;
+
+arm_compute::Status NeonComparisonWorkloadValidate(const TensorInfo& input0,
+                                                   const TensorInfo& input1,
+                                                   const TensorInfo& output,
+                                                   const ComparisonDescriptor& descriptor)
+{
+    const arm_compute::TensorInfo aclInput0 = BuildArmComputeTensorInfo(input0);
+    const arm_compute::TensorInfo aclInput1 = BuildArmComputeTensorInfo(input1);
+    const arm_compute::TensorInfo aclOutput = BuildArmComputeTensorInfo(output);
+
+    const arm_compute::ComparisonOperation comparisonOperation = ConvertComparisonOperationToAcl(descriptor);
+
+    const arm_compute::Status aclStatus = arm_compute::NEElementwiseComparison::validate(&aclInput0,
+                                                                                         &aclInput1,
+                                                                                         &aclOutput,
+                                                                                         comparisonOperation);
+    return aclStatus;
+}
+
+NeonComparisonWorkload::NeonComparisonWorkload(const ComparisonQueueDescriptor& descriptor, const WorkloadInfo& info)
+    : BaseWorkload<ComparisonQueueDescriptor>(descriptor, info)
+{
+    m_Data.ValidateInputsOutputs("NeonComparisonWorkload", 2, 1);
+
+    arm_compute::ITensor& input0 = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
+    arm_compute::ITensor& input1 = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Inputs[1])->GetTensor();
+    arm_compute::ITensor& output = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
+
+    const arm_compute::ComparisonOperation comparisonOperation = ConvertComparisonOperationToAcl(m_Data.m_Parameters);
+
+    m_ComparisonLayer.configure(&input0, &input1, &output, comparisonOperation);
+}
+
+void NeonComparisonWorkload::Execute() const
+{
+    ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonComparisonWorkload_Execute");
+    m_ComparisonLayer.run();
+}
+
+} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/neon/workloads/NeonComparisonWorkload.hpp b/src/backends/neon/workloads/NeonComparisonWorkload.hpp
new file mode 100644
index 0000000..1b01053
--- /dev/null
+++ b/src/backends/neon/workloads/NeonComparisonWorkload.hpp
@@ -0,0 +1,31 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <neon/workloads/NeonWorkloadUtils.hpp>
+
+#include <arm_compute/runtime/NEON/functions/NEElementwiseOperations.h>
+
+namespace armnn
+{
+
+arm_compute::Status NeonComparisonWorkloadValidate(const TensorInfo& input0,
+                                                   const TensorInfo& input1,
+                                                   const TensorInfo& output,
+                                                   const ComparisonDescriptor& descriptor);
+
+class NeonComparisonWorkload : public BaseWorkload<ComparisonQueueDescriptor>
+{
+public:
+    NeonComparisonWorkload(const ComparisonQueueDescriptor& descriptor, const WorkloadInfo& info);
+
+    virtual void Execute() const override;
+
+private:
+    mutable arm_compute::NEElementwiseComparison m_ComparisonLayer;
+};
+
+} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/neon/workloads/NeonGreaterWorkload.cpp b/src/backends/neon/workloads/NeonGreaterWorkload.cpp
deleted file mode 100644
index 1ec5ac4..0000000
--- a/src/backends/neon/workloads/NeonGreaterWorkload.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#include "NeonGreaterWorkload.hpp"
-#include <aclCommon/ArmComputeTensorUtils.hpp>
-#include <backendsCommon/CpuTensorHandle.hpp>
-
-namespace armnn
-{
-
-arm_compute::Status NeonGreaterWorkloadValidate(const TensorInfo& input0,
-                                                const TensorInfo& input1,
-                                                const TensorInfo& output)
-{
-    const arm_compute::TensorInfo aclInput0 = armcomputetensorutils::BuildArmComputeTensorInfo(input0);
-    const arm_compute::TensorInfo aclInput1 = armcomputetensorutils::BuildArmComputeTensorInfo(input1);
-    const arm_compute::TensorInfo aclOutput = armcomputetensorutils::BuildArmComputeTensorInfo(output);
-
-    return arm_compute::NEGreater::validate(&aclInput0,
-                                            &aclInput1,
-                                            &aclOutput);
-}
-
-NeonGreaterWorkload::NeonGreaterWorkload(const GreaterQueueDescriptor& descriptor, const WorkloadInfo& info)
-    : BaseWorkload<GreaterQueueDescriptor>(descriptor, info)
-{
-    m_Data.ValidateInputsOutputs("NeonGreaterWorkload", 2, 1);
-
-    arm_compute::ITensor& input0 = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Inputs[0])->GetTensor();
-    arm_compute::ITensor& input1 = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Inputs[1])->GetTensor();
-    arm_compute::ITensor& output = boost::polymorphic_downcast<IAclTensorHandle*>(m_Data.m_Outputs[0])->GetTensor();
-
-    m_GreaterLayer.configure(&input0, &input1, &output);
-}
-
-void NeonGreaterWorkload::Execute() const
-{
-    ARMNN_SCOPED_PROFILING_EVENT_NEON("NeonGreaterWorkload_Execute");
-    m_GreaterLayer.run();
-}
-
-} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/neon/workloads/NeonGreaterWorkload.hpp b/src/backends/neon/workloads/NeonGreaterWorkload.hpp
deleted file mode 100644
index 503e60e..0000000
--- a/src/backends/neon/workloads/NeonGreaterWorkload.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-//
-// Copyright © 2017 Arm Ltd. All rights reserved.
-// SPDX-License-Identifier: MIT
-//
-
-#pragma once
-
-#include <neon/workloads/NeonWorkloadUtils.hpp>
-
-#include <arm_compute/runtime/NEON/functions/NEElementwiseOperations.h>
-
-namespace armnn
-{
-
-arm_compute::Status NeonGreaterWorkloadValidate(const TensorInfo& input0,
-                                                const TensorInfo& input1,
-                                                const TensorInfo& output);
-
-class NeonGreaterWorkload : public BaseWorkload<GreaterQueueDescriptor>
-{
-public:
-    NeonGreaterWorkload(const GreaterQueueDescriptor& descriptor, const WorkloadInfo& info);
-
-    virtual void Execute() const override;
-
-private:
-    mutable arm_compute::NEGreater m_GreaterLayer;
-};
-
-} //namespace armnn
\ No newline at end of file
diff --git a/src/backends/neon/workloads/NeonWorkloads.hpp b/src/backends/neon/workloads/NeonWorkloads.hpp
index e28d120..2b7eabe 100644
--- a/src/backends/neon/workloads/NeonWorkloads.hpp
+++ b/src/backends/neon/workloads/NeonWorkloads.hpp
@@ -11,6 +11,7 @@
 #include "NeonArgMinMaxWorkload.hpp"
 #include "NeonBatchNormalizationWorkload.hpp"
 #include "NeonBatchToSpaceNdWorkload.hpp"
+#include "NeonComparisonWorkload.hpp"
 #include "NeonConstantWorkload.hpp"
 #include "NeonConvertFp16ToFp32Workload.hpp"
 #include "NeonConvertFp32ToFp16Workload.hpp"
@@ -21,7 +22,6 @@
 #include "NeonDetectionPostProcessWorkload.hpp"
 #include "NeonFloorFloatWorkload.hpp"
 #include "NeonFullyConnectedWorkload.hpp"
-#include "NeonGreaterWorkload.hpp"
 #include "NeonInstanceNormalizationWorkload.hpp"
 #include "NeonL2NormalizationFloatWorkload.hpp"
 #include "NeonLstmFloatWorkload.hpp"