IVGCVSW-5012 Enable zero copy for Neon

 * Allow memory import if padding is not required in Neon
 * AddMockImportBackend for fallback tests
 * Refactor GraphUtils
 * Memory import unit tests
 * Fallback unit tests

Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: Ic2e141e12774bf6d915e77745b6f6d2d83d9b82d
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index f87a69b..ccbfdc6 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -159,6 +159,9 @@
     layerTests/SubtractionTestImpl.hpp
     layerTests/TransposeConvolution2dTestImpl.cpp
     layerTests/TransposeConvolution2dTestImpl.hpp
+    mockBackend/MockImportBackend.cpp
+    mockBackend/MockImportBackend.hpp
+    mockBackend/MockImportLayerSupport.hpp
 )
 
 if (ARMNNREF)
diff --git a/src/backends/backendsCommon/test/mockBackend/MockImportBackend.cpp b/src/backends/backendsCommon/test/mockBackend/MockImportBackend.cpp
new file mode 100644
index 0000000..ebe9434
--- /dev/null
+++ b/src/backends/backendsCommon/test/mockBackend/MockImportBackend.cpp
@@ -0,0 +1,115 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "MockImportBackend.hpp"
+#include "MockImportLayerSupport.hpp"
+
+#include <armnn/BackendRegistry.hpp>
+#include <armnn/backends/IBackendContext.hpp>
+#include <armnn/backends/IMemoryManager.hpp>
+#include <armnn/utility/PolymorphicDowncast.hpp>
+
+#include <reference/RefWorkloadFactory.hpp>
+#include <reference/RefTensorHandleFactory.hpp>
+
+#include <Optimizer.hpp>
+
+namespace armnn
+{
+
+MockImportBackendInitialiser::MockImportBackendInitialiser()
+{
+    BackendRegistryInstance().Register(MockImportBackend::GetIdStatic(),
+                                       []()
+                                       {
+                                           return IBackendInternalUniquePtr(new MockImportBackend);
+                                       });
+}
+
+MockImportBackendInitialiser::~MockImportBackendInitialiser()
+{
+    try
+    {
+        BackendRegistryInstance().Deregister(MockImportBackend::GetIdStatic());
+    }
+    catch (...)
+    {
+        std::cerr << "could not deregister mock import backend" << std::endl;
+    }
+}
+
+const BackendId& MockImportBackend::GetIdStatic()
+{
+    static const BackendId s_Id{ MockImportBackendId() };
+    return s_Id;
+}
+
+IBackendInternal::IWorkloadFactoryPtr MockImportBackend::CreateWorkloadFactory(
+    const IBackendInternal::IMemoryManagerSharedPtr& memoryManager) const
+{
+    return std::make_unique<RefWorkloadFactory>(PolymorphicPointerDowncast<RefMemoryManager>(memoryManager));
+}
+
+IBackendInternal::IWorkloadFactoryPtr MockImportBackend::CreateWorkloadFactory(
+    class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const
+{
+    auto memoryManager = std::make_shared<RefMemoryManager>();
+
+    tensorHandleFactoryRegistry.RegisterMemoryManager(memoryManager);
+    tensorHandleFactoryRegistry.RegisterFactory(std::make_unique<RefTensorHandleFactory>(memoryManager));
+
+    return std::make_unique<RefWorkloadFactory>(PolymorphicPointerDowncast<RefMemoryManager>(memoryManager));
+}
+
+IBackendInternal::IBackendContextPtr MockImportBackend::CreateBackendContext(const IRuntime::CreationOptions&) const
+{
+    return IBackendContextPtr{};
+}
+
+IBackendInternal::IBackendProfilingContextPtr MockImportBackend::CreateBackendProfilingContext(
+    const IRuntime::CreationOptions&, IBackendProfilingPtr&)
+{
+    return IBackendProfilingContextPtr{};
+}
+
+IBackendInternal::IMemoryManagerUniquePtr MockImportBackend::CreateMemoryManager() const
+{
+    return std::make_unique<RefMemoryManager>();
+}
+
+IBackendInternal::Optimizations MockImportBackend::GetOptimizations() const
+{
+    return Optimizations{};
+}
+
+IBackendInternal::ILayerSupportSharedPtr MockImportBackend::GetLayerSupport() const
+{
+    static ILayerSupportSharedPtr layerSupport{new MockImportLayerSupport};
+    return layerSupport;
+}
+
+OptimizationViews MockImportBackend::OptimizeSubgraphView(const SubgraphView& subgraph) const
+{
+    OptimizationViews optimizationViews;
+
+    optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph));
+
+    return optimizationViews;
+}
+
+std::vector<ITensorHandleFactory::FactoryId> MockImportBackend::GetHandleFactoryPreferences() const
+{
+    return std::vector<ITensorHandleFactory::FactoryId> { RefTensorHandleFactory::GetIdStatic() };
+}
+
+void MockImportBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry)
+{
+    auto memoryManager = std::make_shared<RefMemoryManager>();
+
+    registry.RegisterMemoryManager(memoryManager);
+    registry.RegisterFactory(std::make_unique<RefTensorHandleFactory>(memoryManager));
+}
+
+} // namespace armnn
diff --git a/src/backends/backendsCommon/test/mockBackend/MockImportBackend.hpp b/src/backends/backendsCommon/test/mockBackend/MockImportBackend.hpp
new file mode 100644
index 0000000..ecc661f
--- /dev/null
+++ b/src/backends/backendsCommon/test/mockBackend/MockImportBackend.hpp
@@ -0,0 +1,53 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/backends/IBackendInternal.hpp>
+
+namespace armnn
+{
+
+constexpr const char* MockImportBackendId() { return "MockRef"; }
+
+class MockImportBackendInitialiser
+{
+public:
+    MockImportBackendInitialiser();
+    ~MockImportBackendInitialiser();
+};
+
+class MockImportBackend : public IBackendInternal
+{
+public:
+    MockImportBackend()  = default;
+    ~MockImportBackend() = default;
+
+    static const BackendId& GetIdStatic();
+    const BackendId& GetId() const override { return GetIdStatic(); }
+
+    IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override;
+
+    IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+        const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
+
+    IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+        class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry) const override;
+
+    IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override;
+
+    IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(
+        const IRuntime::CreationOptions& creationOptions, IBackendProfilingPtr& backendProfiling) override;
+
+    IBackendInternal::Optimizations GetOptimizations() const override;
+    IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
+
+    OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override;
+
+    std::vector<ITensorHandleFactory::FactoryId> GetHandleFactoryPreferences() const override;
+
+    void RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry) override;
+};
+
+} // namespace armnn
diff --git a/src/backends/backendsCommon/test/mockBackend/MockImportLayerSupport.hpp b/src/backends/backendsCommon/test/mockBackend/MockImportLayerSupport.hpp
new file mode 100644
index 0000000..75e637e
--- /dev/null
+++ b/src/backends/backendsCommon/test/mockBackend/MockImportLayerSupport.hpp
@@ -0,0 +1,46 @@
+//
+// Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/utility/IgnoreUnused.hpp>
+
+#include <backendsCommon/LayerSupportBase.hpp>
+
+namespace armnn
+{
+
+class MockImportLayerSupport : public LayerSupportBase
+{
+public:
+    bool IsAdditionSupported(const TensorInfo& input0,
+                             const TensorInfo& input1,
+                             const TensorInfo& output,
+                             Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override
+    {
+        IgnoreUnused(input0);
+        IgnoreUnused(input1);
+        IgnoreUnused(output);
+        IgnoreUnused(reasonIfUnsupported);
+        return true;
+    }
+
+    bool IsInputSupported(const TensorInfo& input,
+                          Optional<std::string&> reasonIfUnsupported) const override
+    {
+        IgnoreUnused(input);
+        IgnoreUnused(reasonIfUnsupported);
+        return true;
+    }
+
+    bool IsOutputSupported(const TensorInfo& output,
+                           Optional<std::string&> reasonIfUnsupported) const override
+    {
+        IgnoreUnused(output);
+        IgnoreUnused(reasonIfUnsupported);
+        return true;
+    }
+};
+
+} // namespace armnn