IVGCVSW-7525 Add broadcast_to to TFLite Parser

  * Changing the optimizer
  * Changing EndToEnd Tests

Signed-off-by: Idriss Chaouch <idriss.chaouch@arm.com>
Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: Ib581794280322a39cfc5ea3c4e6a6398cf723d5e
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bcfb8cf..a89e3fd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -682,6 +682,7 @@
              src/armnnTfLiteParser/test/AvgPool2D.cpp
              src/armnnTfLiteParser/test/BatchMatMul.cpp
              src/armnnTfLiteParser/test/BatchToSpaceND.cpp
+             src/armnnTfLiteParser/test/BroadcastTo.cpp
              src/armnnTfLiteParser/test/Cast.cpp
              src/armnnTfLiteParser/test/Comparison.cpp
              src/armnnTfLiteParser/test/Concatenation.cpp
diff --git a/docs/05_01_parsers.dox b/docs/05_01_parsers.dox
index f92504b..4454f44 100644
--- a/docs/05_01_parsers.dox
+++ b/docs/05_01_parsers.dox
@@ -123,6 +123,7 @@
 - ARG_MIN
 - AVERAGE_POOL_2D, Supported Fused Activation: RELU , RELU6 , TANH, NONE
 - BATCH_TO_SPACE
+- BROADCAST_TO
 - CAST
 - CEIL
 - CONCATENATION, Supported Fused Activation: RELU , RELU6 , TANH, NONE
diff --git a/src/armnn/layers/BroadcastToLayer.cpp b/src/armnn/layers/BroadcastToLayer.cpp
index 252aa46..26a90ee 100644
--- a/src/armnn/layers/BroadcastToLayer.cpp
+++ b/src/armnn/layers/BroadcastToLayer.cpp
@@ -6,7 +6,6 @@
 #include "BroadcastToLayer.hpp"
 
 #include "LayerCloneBase.hpp"
-
 #include <armnn/TypesUtils.hpp>
 #include <armnn/backends/WorkloadData.hpp>
 #include <armnn/backends/WorkloadFactory.hpp>
diff --git a/src/armnn/optimizations/DeleteBroadcastTo.hpp b/src/armnn/optimizations/DeleteBroadcastTo.hpp
index 9ea2090..38396c1 100644
--- a/src/armnn/optimizations/DeleteBroadcastTo.hpp
+++ b/src/armnn/optimizations/DeleteBroadcastTo.hpp
@@ -20,11 +20,14 @@
     {
         if(layer.GetType() == LayerType::BroadcastTo)
         {
+            TensorInfo info = layer.GetOutputSlot(0).GetTensorInfo();
             Layer& next = layer.GetOutputSlot(0).GetConnection(0)->GetOwningLayer();
             if (next.GetType() == LayerType::ElementwiseBinary)
             {
                 Layer& connectedLayer = layer.GetInputSlots()[0].GetConnectedOutputSlot()->GetOwningLayer();
+                auto tensorInfo = connectedLayer.GetOutputSlot().GetTensorInfo();
                 layer.GetOutputSlot().MoveAllConnections(connectedLayer.GetOutputSlot());
+                connectedLayer.GetOutputSlot().GetOutputHandler().SetTensorInfo(tensorInfo);
             }
         }
     }
diff --git a/src/armnnTfLiteParser/TfLiteParser.cpp b/src/armnnTfLiteParser/TfLiteParser.cpp
index 052aac6..3f4f0d8 100644
--- a/src/armnnTfLiteParser/TfLiteParser.cpp
+++ b/src/armnnTfLiteParser/TfLiteParser.cpp
@@ -750,6 +750,7 @@
     m_ParserFunctions[tflite::BuiltinOperator_AVERAGE_POOL_2D]         = &TfLiteParserImpl::ParseAveragePool2D;
     m_ParserFunctions[tflite::BuiltinOperator_BATCH_TO_SPACE_ND]       = &TfLiteParserImpl::ParseBatchToSpaceND;
     m_ParserFunctions[tflite::BuiltinOperator_BATCH_MATMUL]            = &TfLiteParserImpl::ParseBatchMatMul;
+    m_ParserFunctions[tflite::BuiltinOperator_BROADCAST_TO]            = &TfLiteParserImpl::ParseBroadcastTo;
     m_ParserFunctions[tflite::BuiltinOperator_CEIL]                    = &TfLiteParserImpl::ParseCeil;
     m_ParserFunctions[tflite::BuiltinOperator_CAST]                    = &TfLiteParserImpl::ParseCast;
     m_ParserFunctions[tflite::BuiltinOperator_CONCATENATION]           = &TfLiteParserImpl::ParseConcatenation;
@@ -1894,6 +1895,66 @@
     RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
 }
 
+void TfLiteParserImpl::ParseBroadcastTo(size_t subgraphIndex, size_t operatorIndex)
+{
+     CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
+
+     auto inputs = GetInputs(m_Model, subgraphIndex, operatorIndex);
+     CHECK_VALID_SIZE(inputs.size(), 2);
+
+     auto outputs = GetOutputs(m_Model, subgraphIndex, operatorIndex);
+     CHECK_VALID_SIZE(outputs.size(), 1);
+
+     TensorInfo inputTensorInfo = ToTensorInfo(inputs[0]);
+     TensorInfo shapeTensorInfo = ToTensorInfo(inputs[1]);
+     TensorInfo outputTensorInfo = ToTensorInfo(outputs[0]);
+
+     auto layerName = fmt::format("Broadcast_to:{}:{}", subgraphIndex, operatorIndex);
+
+     BroadcastToDescriptor descriptor;
+
+     auto shapeBufferPtr = GetBuffer(m_Model, inputs[1]->buffer);
+     if (shapeBufferPtr != nullptr)
+     {
+         std::vector<unsigned int> targetShape;
+         unsigned int numElement = shapeTensorInfo.GetNumElements();
+         auto shapeData = reinterpret_cast<const int32_t*>(shapeBufferPtr->data.data());
+         if (shapeData)
+            {
+                for (unsigned int i = 0; i < numElement; ++i)
+                {
+                    targetShape.push_back(armnn::numeric_cast<unsigned int>(shapeData[i]));
+                }
+                descriptor.m_BroadcastToShape = TensorShape(numElement, targetShape.data());
+            }
+         /// get dataShape from outputShape if missing
+         else
+         {
+             if(outputTensorInfo.GetShape().GetNumElements() <= 1)
+             {
+                 ARMNN_THROW_PARSE_EXCEPTION("For Broadcast_to layer, "
+                                             "data and output shape are not found in the buffer.");
+             }
+             descriptor.m_BroadcastToShape = outputTensorInfo.GetShape();
+         }
+     }
+     else
+     {
+             ARMNN_THROW_PARSE_EXCEPTION("For Broadcast_to layer, Shape data was not found in the buffer.");
+     }
+
+     IConnectableLayer* layer = m_Network->AddBroadcastToLayer(descriptor, layerName.c_str());
+     ARMNN_ASSERT(layer != nullptr);
+
+     layer->GetOutputSlot(0).SetTensorInfo(outputTensorInfo);
+
+     auto inputTensorIndexes = AsUnsignedVector(GetInputTensorIds(m_Model, subgraphIndex, operatorIndex));
+     RegisterInputSlots(subgraphIndex, operatorIndex, layer, {inputTensorIndexes[0]});
+
+     auto outputTensorIndexes = AsUnsignedVector(GetOutputTensorIds(m_Model, subgraphIndex, operatorIndex));
+     RegisterOutputSlots(subgraphIndex, operatorIndex, layer, {outputTensorIndexes[0]});
+}
+
 void TfLiteParserImpl::ParseL2Normalization(size_t subgraphIndex, size_t operatorIndex)
 {
     CHECK_MODEL(m_Model, subgraphIndex, operatorIndex);
diff --git a/src/armnnTfLiteParser/TfLiteParser.hpp b/src/armnnTfLiteParser/TfLiteParser.hpp
index e7f2659..f0c7dde 100644
--- a/src/armnnTfLiteParser/TfLiteParser.hpp
+++ b/src/armnnTfLiteParser/TfLiteParser.hpp
@@ -117,6 +117,7 @@
     void ParseAveragePool2D(size_t subgraphIndex, size_t operatorIndex);
     void ParseBatchMatMul(size_t subgraphIndex, size_t operatorIndex);
     void ParseBatchToSpaceND(size_t subgraphIndex, size_t operatorIndex);
+    void ParseBroadcastTo(size_t subgraphIndex, size_t operatorIndex);
     void ParseCast(size_t subgraphIndex, size_t operatorIndex);
     void ParseCeil(size_t subgraphIndex, size_t operatorIndex);
     void ParseComparison(size_t subgraphIndex, size_t operatorIndex, armnn::ComparisonOperation comparisonOperation);
diff --git a/src/armnnTfLiteParser/test/BroadcastTo.cpp b/src/armnnTfLiteParser/test/BroadcastTo.cpp
new file mode 100644
index 0000000..9a5d6c0
--- /dev/null
+++ b/src/armnnTfLiteParser/test/BroadcastTo.cpp
@@ -0,0 +1,508 @@
+//
+// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ParserFlatbuffersFixture.hpp"
+
+TEST_SUITE("TensorflowLiteParser_BroadcastTo")
+{
+struct BroadcastToFixture : public ParserFlatbuffersFixture
+{
+    explicit BroadcastToFixture(const std::string& inputShape1,
+                                const std::string& inputShape2,
+                                const std::string& shapeShape,
+                                const std::string& outputBroadcastToShape,
+                                const std::string& outputShape,
+                                const std::string& shapeData,
+                                const bool checkThrows,
+                                const std::string& scale = "1.0",
+                                const std::string& offset = "0")
+    {
+        m_JsonString = R"(
+        {
+          "version": 3,
+          "operator_codes": [
+            {
+              "deprecated_builtin_code": 127,
+              "version": 2,
+              "builtin_code": "BROADCAST_TO"
+            },
+            {
+              "version": 1,
+              "builtin_code": "MUL"
+            }
+          ],
+          "subgraphs": [
+            {
+              "tensors": [
+                {
+                  "shape": )" + inputShape1 + R"(,
+                  "type": "FLOAT32",
+                  "buffer": 1,
+                  "name": "inputTensor1",
+                  "quantization":{
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "shape_signature": [
+                    -1,
+                    3
+                  ],
+                  "has_rank": true
+                },
+                {
+                  "shape": )" + inputShape2 + R"(,
+                  "type": "FLOAT32",
+                  "buffer": 2,
+                  "name": "inputTensor2",
+                  "quantization": {
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "shape_signature": [
+                    -1,
+                    3
+                  ],
+                  "has_rank": true
+                },
+                {
+                  "shape": )" + shapeShape + R"(,
+                  "type": "INT32",
+                  "buffer": 3,
+                  "name": "shape",
+                  "quantization": {
+                    "details_type": "NONE",
+                    "quantized_dimension": 0
+                  },
+                  "is_variable": false,
+                  "shape_signature": [
+                    -1
+                  ],
+                  "has_rank": true
+                },
+                {
+                  "shape":  )" + outputBroadcastToShape + R"(,
+                  "type": "FLOAT32",
+                  "buffer": 4,
+                  "name": "model/tf.broadcast_to/BroadcastTo",
+                  "quantization": {
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "has_rank": false
+                },
+                {
+                  "shape": )" + outputShape + R"(,
+                  "type": "FLOAT32",
+                  "buffer": 5,
+                  "name": "outputTensor",
+                  "quantization": {
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "has_rank": false
+                }
+              ],
+              "inputs": [
+                0,
+                1,
+                2
+              ],
+              "outputs": [
+                4
+              ],
+              "operators": [
+                {
+                  "opcode_index": 0,
+                  "inputs": [
+                    0,
+                    2
+                  ],
+                  "outputs": [
+                    3
+                  ],
+                  "builtin_options_type": "NONE",
+                  "custom_options_format": "FLEXBUFFERS"
+                },
+                {
+                  "opcode_index": 1,
+                  "inputs": [
+                    1,
+                    3
+                  ],
+                  "outputs": [
+                    4
+                  ],
+                  "builtin_options_type": "MulOptions",
+                  "builtin_options": {
+                    "fused_activation_function": "NONE"
+                  },
+                  "custom_options_format": "FLEXBUFFERS"
+                }
+              ],
+              "name": "main"
+            }
+          ],
+          "description": "MLIR Converted.",
+          "buffers": [
+            {
+            },
+            {
+            },
+            {
+            },
+            {
+             )" + shapeData + R"(
+            },
+            {
+            },
+            {
+            },
+            {
+            },
+            {
+            }
+          ],
+          "metadata": [
+            {
+              "name": "min_runtime_version",
+              "buffer": 6
+            },
+            {
+              "name": "CONVERSION_METADATA",
+              "buffer": 7
+            }
+          ],
+          "signature_defs": [
+
+          ]
+        }
+        )";
+        if(checkThrows)
+        {
+            CHECK_THROWS_AS(Setup(), armnn::ParseException);
+        }
+        else
+        {
+            Setup();
+        }
+    }
+};
+
+struct BroadcastToSimpleFixture : public ParserFlatbuffersFixture
+{
+    explicit BroadcastToSimpleFixture(const std::string& inputShape,
+                                      const std::string& shapeShape,
+                                      const std::string& outputShape,
+                                      const std::string& shapeData,
+                                      const std::string& dataType,
+                                      const std::string& scale = "1.0",
+                                      const std::string& offset = "0")
+    {
+        m_JsonString = R"(
+        {
+          "version": 3,
+          "operator_codes": [
+            {
+              "deprecated_builtin_code": 127,
+              "version": 2,
+              "builtin_code": "BROADCAST_TO"
+            }
+          ],
+          "subgraphs": [
+            {
+              "tensors": [
+                {
+                  "shape": )" + inputShape + R"(,
+                  "type": )" + dataType + R"(,
+                  "buffer": 1,
+                  "name": "input1",
+                  "quantization": {
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "shape_signature": [
+                    -1,
+                    3
+                  ],
+                  "has_rank": true
+                },
+                {
+                  "shape": )" + shapeShape + R"(,
+                  "type": "INT32",
+                  "buffer": 2,
+                  "name": "shape",
+                  "quantization": {
+                    "details_type": "NONE",
+                    "quantized_dimension": 0
+                  },
+                  "is_variable": false,
+                  "shape_signature": [
+                    -1
+                  ],
+                  "has_rank": true
+                },
+                {
+                  "shape": )" + outputShape + R"(,
+                  "type": )" + dataType + R"(,
+                  "buffer": 3,
+                  "name": "Identity",
+                  "quantization": {
+                        "min": [ 0.0 ],
+                        "max": [ 255.0 ],
+                        "scale": [ )" + scale + R"( ],
+                        "zero_point": [ )" + offset + R"( ],
+                  },
+                  "is_variable": false,
+                  "has_rank": false
+                }
+              ],
+              "inputs": [
+                0,
+                1
+              ],
+              "outputs": [
+                2
+              ],
+              "operators": [
+                {
+                  "opcode_index": 0,
+                  "inputs": [
+                    0,
+                    1
+                  ],
+                  "outputs": [
+                    2
+                  ],
+                  "builtin_options_type": "NONE",
+                  "custom_options_format": "FLEXBUFFERS"
+                }
+              ],
+              "name": "main"
+            }
+          ],
+          "description": "MLIR Converted.",
+          "buffers": [
+            {
+            },
+            {
+            },
+            {
+                "data": )" + shapeData + R"(,
+            },
+            {
+            },
+            {
+            },
+            {
+            }
+          ],
+          "metadata": [
+            {
+              "name": "min_runtime_version",
+              "buffer": 4
+            },
+            {
+              "name": "CONVERSION_METADATA",
+              "buffer": 5
+            }
+          ],
+          "signature_defs": [
+
+          ]
+        }
+    )";
+        SetupSingleInputSingleOutput("inputTensor", "outputTensor");
+    }
+};
+
+struct SimpleBroadcastToSimpleFixtureFloat32 : public BroadcastToSimpleFixture
+{
+    SimpleBroadcastToSimpleFixtureFloat32() : BroadcastToSimpleFixture("[1, 4]",
+                                                                       "[2]",
+                                                                       "[3, 4]",
+                                                                       "[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                                       "FLOAT32") {}
+};
+
+TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureFloat32, "SimpleParseBroadcastToFloat32")
+{
+    RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32>
+            (0, {{ "input1",  { 1.f, 2.f, 3.f, 4.f }}},
+             {{ "Identity", { 1.f, 2.f, 3.f, 4.f,
+                              1.f, 2.f, 3.f, 4.f,
+                              1.f, 2.f, 3.f, 4.f}}});
+
+}
+struct SimpleBroadcastToSimpleFixtureSigned32 : public BroadcastToSimpleFixture
+{
+    SimpleBroadcastToSimpleFixtureSigned32() : BroadcastToSimpleFixture("[1, 4]",
+                                                                        "[2]",
+                                                                        "[3, 4]",
+                                                                        "[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                                        "INT32") {}
+};
+
+TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureSigned32, "SimpleParseBroadcastToSigned32")
+{
+    RunTest<2, armnn::DataType::Signed32, armnn::DataType::Signed32>
+            (0, {{ "input1",  { 1, 2, 3, -4 }}},
+             {{ "Identity", { 1, 2, 3, -4,
+                              1, 2, 3, -4,
+                              1, 2, 3, -4}}});
+
+}
+
+struct SimpleBroadcastToSimpleFixtureQAsymmU8 : public BroadcastToSimpleFixture
+{
+    SimpleBroadcastToSimpleFixtureQAsymmU8() : BroadcastToSimpleFixture("[1, 4]",
+                                                                        "[2]",
+                                                                        "[3, 4]",
+                                                                        "[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                                        "UINT8") {}
+};
+
+TEST_CASE_FIXTURE(SimpleBroadcastToSimpleFixtureQAsymmU8, "SimpleParseBroadcastToQAsymmU8")
+{
+    RunTest<2, armnn::DataType::QAsymmU8, armnn::DataType::QAsymmU8>
+            (0, {{ "input1",  { 1, 2, 3, 4 }}},
+             {{ "Identity", { 1, 2, 3, 4,
+                              1, 2, 3, 4,
+                              1, 2, 3, 4}}});
+
+}
+
+struct SimpleBroadcastToFixture : public BroadcastToFixture
+{
+    SimpleBroadcastToFixture() : BroadcastToFixture("[1, 4]",
+                                                    "[3, 4]",
+                                                    "[2]",
+                                                    "[3, 4]",
+                                                    "[3, 4]",
+                                                    "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                    false) {}
+};
+
+TEST_CASE_FIXTURE(SimpleBroadcastToFixture, "ParseBroadcastTo")
+{
+    RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32>
+            (
+                    0, {{ "inputTensor1",  { 1, 2, 3, 4 }}},
+                    {{"inputTensor2", {1, 1, 1, 1,
+                                       1, 1, 1, 1,
+                                       1, 1, 1, 1}}},
+                    {{ "outputTensor", { 1, 2, 3, 4,
+                                         1, 2, 3, 4,
+                                         1, 2, 3, 4}}}
+            );
+
+}
+
+struct DynamicBroadcastToFixture : public BroadcastToFixture
+{
+    DynamicBroadcastToFixture() : BroadcastToFixture("[1, 4]",
+                                                     "[3, 4]",
+                                                     "[2]",
+                                                     "[3, 4]",
+                                                     "[3, 4]",
+                                                     "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                     false) {}
+};
+
+TEST_CASE_FIXTURE(DynamicBroadcastToFixture, "DynamicParseBroadcastTo")
+{
+    RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32>
+            (
+                    0, {{ "inputTensor1",  { 1, 2, 3, 4 }}},
+                    {{"inputTensor2", {1, 1, 1, 1,
+                                       1, 1, 1, 1,
+                                       1, 1, 1, 1}}},
+                    {{ "outputTensor", { 1, 2, 3, 4,
+                                         1, 2, 3, 4,
+                                         1, 2, 3, 4}}}
+            );
+
+}
+
+struct DynamicBroadcastToFixtureNoOutputShape : public BroadcastToFixture
+{
+    DynamicBroadcastToFixtureNoOutputShape() : BroadcastToFixture("[1, 4]",
+                                                     "[3, 4]",
+                                                     "[2]",
+                                                     "[]",
+                                                     "[3, 4]",
+                                                     "\"data\":[3, 0, 0, 0, 4, 0, 0, 0]",
+                                                     false) {}
+};
+
+TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoOutputShape, "DynamicParseBroadcastToNoOutputShape")
+{
+    RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32>
+            (
+                    0, {{ "inputTensor1",  { 1, 2, 3, 4 }}},
+                    {{"inputTensor2", {1, 1, 1, 1,
+                                       1, 1, 1, 1,
+                                       1, 1, 1, 1}}},
+                    {{ "outputTensor", { 1, 2, 3, 4,
+                                         1, 2, 3, 4,
+                                         1, 2, 3, 4}}}
+            );
+
+}
+
+struct DynamicBroadcastToFixtureNoData : public BroadcastToFixture
+{
+    DynamicBroadcastToFixtureNoData() : BroadcastToFixture("[1, 4]",
+                                                                  "[3, 4]",
+                                                                  "[2]",
+                                                                  "[3, 4]",
+                                                                  "[3, 4]",
+                                                                  "",
+                                                                  false) {}
+};
+
+TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoData, "DynamicParseBroadcastToNoData")
+{
+    RunTest<2, armnn::DataType::Float32, armnn::DataType::Float32, armnn::DataType::Float32>
+            (
+                    0, {{ "inputTensor1",  { 1, 2, 3, 4 }}},
+                    {{"inputTensor2", {1, 1, 1, 1,
+                                       1, 1, 1, 1,
+                                       1, 1, 1, 1}}},
+                    {{ "outputTensor", { 1, 2, 3, 4,
+                                         1, 2, 3, 4,
+                                         1, 2, 3, 4}}}
+            );
+
+}
+
+struct DynamicBroadcastToFixtureNoDataNoOutputShape : public BroadcastToFixture
+{
+    DynamicBroadcastToFixtureNoDataNoOutputShape() : BroadcastToFixture("[1, 4]",
+                                                           "[3, 4]",
+                                                           "[2]",
+                                                           "[]",
+                                                           "[3, 4]",
+                                                           "", true) {  }
+};
+
+TEST_CASE_FIXTURE(DynamicBroadcastToFixtureNoDataNoOutputShape, "DynamicParseBroadcastToNoDataNoOutputShape")
+{
+}
+}
\ No newline at end of file
diff --git a/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp b/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp
index 3b2c47f..f9de3b9 100644
--- a/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp
+++ b/src/backends/backendsCommon/test/BroadcastToEndToEndTestImpl.hpp
@@ -87,7 +87,8 @@
     }
 
     template <armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
-    void BroadcastToEndToEndElementWiseBinary(const std::vector<BackendId>& backends)
+    void BroadcastToEndToEndElementWiseBinary(const std::vector<BackendId>& backends,
+                                              const ElementwiseBinaryDescriptor& elementWiseDescriptor)
     {
         float   qScale  = 1.0f;
         int32_t qOffset = 0;
@@ -114,17 +115,39 @@
                                                                                    1, 1, 1, 1
                                                                            }, qScale, qOffset);
 
-        std::vector<T> expectedOutputData = armnnUtils::QuantizedVector<T>({
-                                                                                   65, 144, 91, 161,
-                                                                                   65, 144, 91, 161,
-                                                                                   65, 144, 91, 161,
-                                                                                   65, 144, 91, 161
-                                                                           }, qScale, qOffset);
+        std::vector<T> expectedOutputData;
+        if (elementWiseDescriptor.m_Operation == BinaryOperation::Mul ||
+            elementWiseDescriptor.m_Operation == BinaryOperation::Div) {
+            expectedOutputData = armnnUtils::QuantizedVector<T>({
+                                                                        65, 144, 91, 161,
+                                                                        65, 144, 91, 161,
+                                                                        65, 144, 91, 161,
+                                                                        65, 144, 91, 161
+                                                                }, qScale, qOffset);
+        }
+        else if (elementWiseDescriptor.m_Operation == BinaryOperation::Add)
+        {
+            expectedOutputData = armnnUtils::QuantizedVector<T>({
+                                                                66, 145, 92, 162,
+                                                                66, 145, 92, 162,
+                                                                66, 145, 92, 162,
+                                                                66, 145, 92, 162
+                                                                }, qScale, qOffset);
+        }
+        else if (elementWiseDescriptor.m_Operation == BinaryOperation::Sub)
+        {
+            expectedOutputData = armnnUtils::QuantizedVector<T>({
+                                                                64, 143, 90, 160,
+                                                                64, 143, 90, 160,
+                                                                64, 143, 90, 160,
+                                                                64, 143, 90, 160
+                                                                }, qScale, qOffset);
+        }
 
         auto descriptor = armnn::BroadcastToDescriptor(armnn::TensorShape({ 4, 4 }));
         CHECK(descriptor.m_BroadcastToShape == outputTensorShape);
         INetworkPtr network = CreateBroadcastToNetworkWithElementWiseBinary(descriptor,
-                                                                            BinaryOperation::Mul,
+                                                                            elementWiseDescriptor,
                                                                             inputInfo,
                                                                             inputInfoElementWise,
                                                                             outputInfo);
diff --git a/src/backends/reference/test/RefEndToEndTests.cpp b/src/backends/reference/test/RefEndToEndTests.cpp
index e503d3f..13995f5 100644
--- a/src/backends/reference/test/RefEndToEndTests.cpp
+++ b/src/backends/reference/test/RefEndToEndTests.cpp
@@ -1736,8 +1736,27 @@
     BroadcastToEndToEnd<armnn::DataType::Float32>(defaultBackends);
 }
 
-TEST_CASE("RefBroadcastToEndToEndWithElementWiseBinaryFloat32")
+TEST_CASE("RefBroadcastToEndToEndWithMultiplicationFloat32")
 {
-    BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends);
+    BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends,
+                                                                   BinaryOperation::Mul);
+}
+
+TEST_CASE("RefBroadcastToEndToEndWithDivisionFloat32")
+{
+    BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends,
+                                                                   BinaryOperation::Div);
+}
+
+TEST_CASE("RefBroadcastToEndToEndWithAdditionFloat32")
+{
+    BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends,
+                                                                   BinaryOperation::Add);
+}
+
+TEST_CASE("RefBroadcastToEndToEndWithSubtractionFloat32")
+{
+    BroadcastToEndToEndElementWiseBinary<armnn::DataType::Float32>(defaultBackends,
+                                                                   BinaryOperation::Sub);
 }
 }