IVGCVSW-7173 Add Rsqrt to Tosa Ref Backend

* Added ElementwiseUnary support with a mapping for Rsqrt
* Added unittests
* Added Rsqrt EndtoEnd tests for all backends
* Changed TosaRefLayerSupport to default to false on unsupported layers


Signed-off-by: David Monahan <david.monahan@arm.com>
Change-Id: I3eaa9c684647ead61520a563815581aa68bee51b
diff --git a/src/backends/backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp
index 3f530cc..9586417 100644
--- a/src/backends/backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2019 Arm Ltd. All rights reserved.
+// Copyright © 2020-2021, 2023 Arm Ltd. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 #pragma once
@@ -47,8 +47,7 @@
 template<armnn::DataType ArmnnInType,
          typename TInput = armnn::ResolveType<ArmnnInType>>
 void ElementwiseUnarySimpleEndToEnd(const std::vector<BackendId>& backends,
-                                    UnaryOperation operation,
-                                    const std::vector<float> expectedOutput)
+                                    UnaryOperation operation)
 {
     using namespace armnn;
 
@@ -63,8 +62,30 @@
 
     CHECK(net);
 
-    const std::vector<float> input({ 1, -1, 1, 1,  5, -5, 5, 5,
-                                       -3, 3, 3, 3,  4, 4, -4, 4 });
+    std::vector<float> input;
+    std::vector<float> expectedOutput;
+    switch(operation)
+    {
+        case UnaryOperation::Abs:
+            input = { 1, -1, 1, 1,  5, -5, 5, 5,
+                      -3, 3, 3, 3,  4, 4, -4, 4 };
+            expectedOutput = { 1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
+                               3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f };
+            break;
+        case UnaryOperation::Rsqrt:
+            input = { 1, 1, 1, 1,  5, 5, 5, 5,
+                      3, 3, 3, 3,  4, 4, 4, 4 };
+            expectedOutput = { 1.f, 1.f, 1.f, 1.f, 0.447214f, 0.447214f, 0.447214f, 0.447214f,
+                               0.57735f, 0.57735f, 0.57735f, 0.57735f, 0.5f, 0.5f, 0.5f, 0.5f };
+            break;
+        default:
+            input = { 1, -1, 1, 1,  5, -5, 5, 5,
+                      -3, 3, 3, 3,  4, 4, -4, 4 };
+            expectedOutput = { 1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
+                               3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f };
+            break;
+    }
+
 
     // quantize data
     std::vector<TInput> qInputData      = armnnUtils::QuantizedVector<TInput>(input, qScale, qOffset);
diff --git a/src/backends/cl/test/ClEndToEndTests.cpp b/src/backends/cl/test/ClEndToEndTests.cpp
index d5ac8b1..4ff2b79 100644
--- a/src/backends/cl/test/ClEndToEndTests.cpp
+++ b/src/backends/cl/test/ClEndToEndTests.cpp
@@ -31,18 +31,18 @@
 {
 std::vector<armnn::BackendId> clDefaultBackends = {armnn::Compute::GpuAcc};
 
+// ElementwiseUnary
 // Abs
 TEST_CASE("ClAbsEndToEndTestFloat32")
 {
-    std::vector<float> expectedOutput =
-    {
-        1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
-        3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f
-    };
-
     ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(clDefaultBackends,
-                                                             UnaryOperation::Abs,
-                                                             expectedOutput);
+                                                             UnaryOperation::Abs);
+}
+// Rsqrt
+TEST_CASE("ClRsqrtEndToEndTestFloat32")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(clDefaultBackends,
+                                                             UnaryOperation::Rsqrt);
 }
 
 // Addition
diff --git a/src/backends/neon/test/NeonEndToEndTests.cpp b/src/backends/neon/test/NeonEndToEndTests.cpp
index d74c501..b930004 100644
--- a/src/backends/neon/test/NeonEndToEndTests.cpp
+++ b/src/backends/neon/test/NeonEndToEndTests.cpp
@@ -33,18 +33,18 @@
 {
 std::vector<armnn::BackendId> neonDefaultBackends = {armnn::Compute::CpuAcc};
 
+// ElementwiseUnary
 // Abs
 TEST_CASE("NeonAbsEndToEndTestFloat32")
 {
-    std::vector<float> expectedOutput =
-    {
-        1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
-        3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f
-    };
-
     ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(neonDefaultBackends,
-                                                             UnaryOperation::Abs,
-                                                             expectedOutput);
+                                                             UnaryOperation::Abs);
+}
+// Rsqrt
+TEST_CASE("NeonRsqrtEndToEndTestFloat32")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(neonDefaultBackends,
+                                                             UnaryOperation::Rsqrt);
 }
 
 // Constant
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index 8fcb3d1..6ff5771 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -43,46 +43,43 @@
 {
 std::vector<armnn::BackendId> defaultBackends = {armnn::Compute::CpuRef};
 
+// ElementwiseUnary
 // Abs
 TEST_CASE("RefAbsEndToEndTestFloat32")
 {
-    std::vector<float> expectedOutput =
-    {
-        1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
-        3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f
-    };
-
     ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(defaultBackends,
-                                                             UnaryOperation::Abs,
-                                                             expectedOutput);
+                                                             UnaryOperation::Abs);
 }
 
 TEST_CASE("RefAbsEndToEndTestUint8")
 {
-    // Note the expected output will be implicitly quantized by the below test function
-    std::vector<float> expectedOutput =
-    {
-        1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
-        3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f
-    };
-
     ElementwiseUnarySimpleEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends,
-                                                                     UnaryOperation::Abs,
-                                                                     expectedOutput);
+                                                              UnaryOperation::Abs);
 }
 
 TEST_CASE("RefAbsEndToEndTestInt16")
 {
-    // Note the expected output will be implicitly quantized by the below test function
-    std::vector<float> expectedOutput =
-    {
-        1.f, 1.f, 1.f, 1.f, 5.f, 5.f, 5.f, 5.f,
-        3.f, 3.f, 3.f, 3.f, 4.f, 4.f, 4.f, 4.f
-    };
-
     ElementwiseUnarySimpleEndToEnd<armnn::DataType::QSymmS16>(defaultBackends,
-                                                                     UnaryOperation::Abs,
-                                                                     expectedOutput);
+                                                              UnaryOperation::Abs);
+}
+
+// Rsqrt
+TEST_CASE("RefRsqrtEndToEndTestFloat32")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(defaultBackends,
+                                                             UnaryOperation::Rsqrt);
+}
+
+TEST_CASE("RefRsqrtEndToEndTestUint8")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::QAsymmU8>(defaultBackends,
+                                                              UnaryOperation::Rsqrt);
+}
+
+TEST_CASE("RefRsqrtEndToEndTestInt16")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::QSymmS16>(defaultBackends,
+                                                              UnaryOperation::Rsqrt);
 }
 
 // Addition
diff --git a/src/backends/tosaCommon/TosaMappings.cpp b/src/backends/tosaCommon/TosaMappings.cpp
index 0b5fa1a..3932b62 100644
--- a/src/backends/tosaCommon/TosaMappings.cpp
+++ b/src/backends/tosaCommon/TosaMappings.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -29,6 +29,11 @@
         {
             return ConvertElementwiseBinaryToTosaOperator(layer, type, inputs, outputs);
         }
+        case LayerType::ElementwiseUnary:
+        {
+            auto unaryDesc = PolymorphicDowncast<const ElementwiseUnaryDescriptor*>(&descriptor);
+            return ConvertElementwiseUnaryOperator(layer, inputs, outputs, unaryDesc);
+        }
         case LayerType::Concat:
         {
             auto concatDesc = PolymorphicDowncast<const OriginsDescriptor*>(&descriptor);
diff --git a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
index 2ec052c..26f51b6 100644
--- a/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
+++ b/src/backends/tosaCommon/operatorMappings/CMakeLists.txt
@@ -1,5 +1,5 @@
 #
-# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 # SPDX-License-Identifier: MIT
 #
 
@@ -14,6 +14,8 @@
         Conv2dOperator.cpp
         ElementwiseBinaryOperator.hpp
         ElementwiseBinaryOperator.cpp
+        ElementwiseUnaryOperator.cpp
+        ElementwiseUnaryOperator.hpp
         Pooling2DOperator.hpp
         Pooling2DOperator.cpp
         ReshapeOperator.hpp
diff --git a/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.cpp b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.cpp
new file mode 100644
index 0000000..15fb9d7
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ElementwiseUnaryOperator.hpp"
+
+TosaSerializationBasicBlock* ConvertElementwiseUnaryOperator(const Layer* layer,
+                                                             const std::vector<const TensorInfo*>& inputs,
+                                                             const std::vector<const TensorInfo*>& outputs,
+                                                             const ElementwiseUnaryDescriptor* unaryDescriptor)
+{
+    std::string input0Name = std::string("input0_");
+    std::string outputName = std::string("output0_");
+    std::string blockName  = std::string("Op_ELEMENTWISEUNARY_block_") + GetUniqueTosaMappingID();
+
+
+    // If a layer is present then the block will be used for execution, so input and output names need to be determined
+    // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
+    if(layer != nullptr)
+    {
+        // Get the layer connected to the input slot and determine unique the tensor name.
+        Layer& connectedLayer0 = layer->GetInputSlot(0).GetConnectedOutputSlot()->GetOwningLayer();
+        input0Name = GenerateUniqueName(connectedLayer0, 0);
+
+        // Determine unique output tensor name.
+        outputName = GenerateUniqueOutputName(*layer, 0);
+    }
+
+    TosaSerializationOperator* op = nullptr;
+    switch(unaryDescriptor->m_Operation)
+    {
+        case UnaryOperation::Rsqrt:
+        {
+            op = new TosaSerializationOperator(tosa::Op_RSQRT,
+                                               Attribute_NONE,
+                                               nullptr,
+                                               {input0Name},
+                                               {outputName});
+            blockName = std::string("Op_RSQRT_block_") + GetUniqueTosaMappingID();
+            break;
+        }
+        default:
+            throw armnn::Exception("ConvertElementwiseUnaryToTosaOperator: Unsupported layer type.");
+    }
+
+    ARMNN_ASSERT(op != nullptr);
+
+    std::vector<TosaSerializationTensor*> tensors;
+    // Only add input tensor if connected layer is an input layer.
+    // As intermediate or constant tensors will be created separately.
+    // There also can't be duplicate tensor.
+    if(input0Name.find("input0_") != std::string::npos)
+    {
+        std::vector<int32_t> inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
+        DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());
+        tensors.push_back(new TosaSerializationTensor(input0Name, inputShape0, inputDType0, {}));
+    }
+
+    std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
+    DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());
+
+    tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
+
+    // operatorInputNames/operatorOutputNames ends up being the same as
+    // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
+    return new TosaSerializationBasicBlock(blockName, // name
+                                           {op}, // operators
+                                           tensors, // tensors
+                                           {input0Name}, // inputs
+                                           {outputName}); // outputs
+}
\ No newline at end of file
diff --git a/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp
new file mode 100644
index 0000000..d13428c
--- /dev/null
+++ b/src/backends/tosaCommon/operatorMappings/ElementwiseUnaryOperator.hpp
@@ -0,0 +1,19 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include "TosaOperatorUtils.hpp"
+#include <Layer.hpp>
+
+#include <tosa_serialization_handler.h>
+
+using namespace armnn;
+using namespace tosa;
+
+TosaSerializationBasicBlock* ConvertElementwiseUnaryOperator(const Layer* layer,
+                                                             const std::vector<const TensorInfo*>& inputs,
+                                                             const std::vector<const TensorInfo*>& outputs,
+                                                             const ElementwiseUnaryDescriptor* unaryDescriptor);
diff --git a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
index 3f27371..66dc1b3 100644
--- a/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
+++ b/src/backends/tosaCommon/operatorMappings/TosaCommonOperators.hpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -10,6 +10,7 @@
 #include "ConstantOperator.hpp"
 #include "Conv2dOperator.hpp"
 #include "ElementwiseBinaryOperator.hpp"
+#include "ElementwiseUnaryOperator.hpp"
 #include "Pooling2DOperator.hpp"
 #include "ReshapeOperator.hpp"
 #include "SliceOperator.hpp"
diff --git a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
index 4cc3791..6e532ab 100644
--- a/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
+++ b/src/backends/tosaCommon/test/OneToOneMappingTests.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -252,6 +252,56 @@
     AssertTosaOneToOneMappingBasicBlock(
         basicBlock, inputShape, outputShape, Op_CONV2D, Attribute_ConvAttribute, descriptor, LayerType::Convolution2d);
 }
+TEST_CASE("GetTosaMapping_ElementwiseUnaryLayerRsqrt")
+{
+    TensorInfo inputInfo  = TensorInfo({ 2, 2 }, DataType::Float32, 0.0f, 0, true);
+    TensorInfo outputInfo = TensorInfo({ 2, 2 }, DataType::Float32, 0.0f, 0, true);
+    std::vector<std::vector<int32_t>> inputShape  = {{ 2, 2 }};
+    std::vector<std::vector<int32_t>> outputShape = {{ 2, 2 }};
+
+    ElementwiseUnaryDescriptor unaryDescriptor = ElementwiseUnaryDescriptor(UnaryOperation::Rsqrt);
+    TosaSerializationBasicBlock* basicBlock =
+            GetTosaMapping(nullptr, LayerType::ElementwiseUnary, {&inputInfo,}, {&outputInfo}, unaryDescriptor);
+
+    AssertTosaOneToOneMappingBasicBlock(basicBlock,
+                                        inputShape,
+                                        outputShape,
+                                        tosa::Op_RSQRT,
+                                        tosa::Attribute_NONE,
+                                        unaryDescriptor,
+                                        LayerType::ElementwiseUnary);
+}
+TEST_CASE("GetTosaMappingFromLayer_ElementwiseUnaryLayerRsqrt")
+{
+    IRuntime::CreationOptions options;
+    IRuntimePtr runtime(IRuntime::Create(options));
+
+    // Builds up the structure of the network.
+    INetworkPtr net(INetwork::Create());
+    ElementwiseUnaryDescriptor unaryDescriptor = ElementwiseUnaryDescriptor(UnaryOperation::Rsqrt);
+    IConnectableLayer* input     = net->AddInputLayer(0, "input0");
+    IConnectableLayer* unaryRsqrt = net->AddElementwiseUnaryLayer(unaryDescriptor, "rsqrt");
+    IConnectableLayer* output    = net->AddOutputLayer(0, "output");
+
+    input->GetOutputSlot(0).Connect(unaryRsqrt->GetInputSlot(0));
+    unaryRsqrt->GetOutputSlot(0).Connect(output->GetInputSlot(0));
+    TensorInfo inputInfo  = TensorInfo({ 2, 2 }, DataType::Float32, 0.0f, 0, true);
+    TensorInfo outputInfo = TensorInfo({ 2, 2 }, DataType::Float32, 0.0f, 0, true);
+    input->GetOutputSlot(0).SetTensorInfo(inputInfo);
+    unaryRsqrt->GetOutputSlot(0).SetTensorInfo(outputInfo);
+    std::vector<std::vector<int32_t>> inputShape  = {{ 2, 2 }};
+    std::vector<std::vector<int32_t>> outputShape = {{ 2, 2 }};
+
+    TosaSerializationBasicBlock* basicBlock =
+            GetTosaMappingFromLayer(PolymorphicDowncast<Layer*>(unaryRsqrt));
+    AssertTosaOneToOneMappingBasicBlock(basicBlock,
+                                        inputShape,
+                                        outputShape,
+                                        tosa::Op_RSQRT,
+                                        tosa::Attribute_NONE,
+                                        unaryDescriptor,
+                                        LayerType::ElementwiseUnary);
+}
 
 TEST_CASE("GetTosaMapping_MultiplicationLayer")
 {
diff --git a/src/backends/tosaReference/TosaRefLayerSupport.cpp b/src/backends/tosaReference/TosaRefLayerSupport.cpp
index 6113b58..238801c 100644
--- a/src/backends/tosaReference/TosaRefLayerSupport.cpp
+++ b/src/backends/tosaReference/TosaRefLayerSupport.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -68,6 +68,7 @@
             }
             break;
         }
+        case LayerType::ElementwiseUnary:
         case LayerType::Pooling2d:
         case LayerType::Reshape:
         case LayerType::Slice:
@@ -89,7 +90,8 @@
             break;
         }
         default:
-            break;
+            // Default to false for all unsupported layers.
+            return false;
     }
 
     auto mappings = GetTosaMapping(nullptr, type, inputInfos, outputInfos, descriptor);
diff --git a/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp b/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
index e19462e..26cadd2 100644
--- a/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
+++ b/src/backends/tosaReference/test/TosaRefEndToEndTests.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -11,6 +11,7 @@
 #include "backendsCommon/test/MultiplicationEndToEndTestImpl.hpp"
 #include "backendsCommon/test/Pooling2dEndToEndTestImpl.hpp"
 #include "backendsCommon/test/ReshapeEndToEndTestImpl.hpp"
+#include "backendsCommon/test/ElementwiseUnaryEndToEndTestImpl.hpp"
 #include "backendsCommon/test/SliceEndToEndTestImpl.hpp"
 #include "backendsCommon/test/SubtractionEndToEndTestImpl.hpp"
 #include "backendsCommon/test/TransposeConvolution2dEndToEndTestImpl.hpp"
@@ -138,6 +139,12 @@
     ReshapeEndToEndFloat16<DataType::Float16>(tosaDefaultBackends);
 }
 
+TEST_CASE("TosaRefRsqrtEndtoEndTestFloat32")
+{
+    ElementwiseUnarySimpleEndToEnd<armnn::DataType::Float32>(tosaDefaultBackends,
+                                                             UnaryOperation::Rsqrt);
+}
+
 // Slice
 TEST_CASE("TosaRefSliceEndtoEndTestFloat32")
 {
diff --git a/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp b/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
index 66dfbe8..e32894f 100644
--- a/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
+++ b/src/backends/tosaReference/test/TosaRefLayerSupportTests.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
 // SPDX-License-Identifier: MIT
 //
 
@@ -374,6 +374,46 @@
     CHECK(!supported);
 }
 
+TEST_CASE("IsLayerSupportedTosaReferenceRsqrt")
+{
+    TensorShape shape0 = {2,2};
+    TensorShape outShape = {2,2};
+    TensorInfo in0(shape0, DataType::Float32);
+    TensorInfo out(outShape, DataType::Float32);
+
+    ElementwiseUnaryDescriptor desc(UnaryOperation::Rsqrt);
+    TosaRefLayerSupport supportChecker;
+    std::string reasonIfNotSupported;
+    auto supported = supportChecker.IsLayerSupported(LayerType::ElementwiseUnary,
+                                                     {in0, out},
+                                                     desc,
+                                                     EmptyOptional(),
+                                                     EmptyOptional(),
+                                                     reasonIfNotSupported);
+
+    CHECK(supported);
+}
+
+TEST_CASE("IsLayerSupportedTosaReferenceRsqrtUnsupported")
+{
+    TensorShape shape0 = {1,1,3,4};
+    TensorShape outShape = {1,3,1,4};
+    TensorInfo in0(shape0, DataType::Signed64);
+    TensorInfo out(outShape, DataType::Signed64);
+
+    ElementwiseUnaryDescriptor desc(UnaryOperation::Rsqrt);
+    TosaRefLayerSupport supportChecker;
+    std::string reasonIfNotSupported;
+    auto supported = supportChecker.IsLayerSupported(LayerType::ElementwiseUnary,
+                                                     {in0, out},
+                                                     desc,
+                                                     EmptyOptional(),
+                                                     EmptyOptional(),
+                                                     reasonIfNotSupported);
+
+    CHECK(!supported);
+}
+
 TEST_CASE("IsLayerSupportedTosaReferenceSlice")
 {
     TensorShape inShape = {3,2,3};