IVGCVSW-7957 Fix weights checking when converting in Support Library

* An Operand can only have NO_VALUE if it is an optional argument
  of an operation
* Add a check to see if the operand is optional to IsWeightsValid

Signed-off-by: Kevin May <kevin.may@arm.com>
Change-Id: Ib22cb7e60f6121d64f8a3bf6cb8c3d13930aa315
diff --git a/shim/sl/canonical/ConversionUtils.cpp b/shim/sl/canonical/ConversionUtils.cpp
index b648548..8c31a92 100644
--- a/shim/sl/canonical/ConversionUtils.cpp
+++ b/shim/sl/canonical/ConversionUtils.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
 //
 
@@ -133,7 +133,8 @@
 
 bool IsWeightsValid(const Operation& operation,
                     uint32_t inputIndex,
-                    const Model& model)
+                    const Model& model,
+                    const bool isOptional = true)
 {
     const Operand* operand = GetInputOperand(operation, inputIndex, model);
     if (!operand)
@@ -141,7 +142,11 @@
         Fail("%s: failed to get input operand %i", __func__, inputIndex);
         return false;
     }
-
+    // If the operand is not an optional operand it cannot have a NO_VALUE lifetime
+    if (!isOptional && operand->lifetime == OperandLifeTime::NO_VALUE)
+    {
+        return false;
+    }
     if (operand->lifetime    != OperandLifeTime::CONSTANT_COPY
         && operand->lifetime != OperandLifeTime::CONSTANT_REFERENCE
         && operand->lifetime != OperandLifeTime::NO_VALUE)
diff --git a/shim/sl/canonical/ConversionUtils.hpp b/shim/sl/canonical/ConversionUtils.hpp
index f595db2..d4b4d92 100644
--- a/shim/sl/canonical/ConversionUtils.hpp
+++ b/shim/sl/canonical/ConversionUtils.hpp
@@ -705,7 +705,7 @@
            lifetime == OperandLifeTime::NO_VALUE;
 }
 
-bool IsWeightsValid(const Operation& operation, uint32_t inputIndex, const Model& model);
+bool IsWeightsValid(const Operation& operation, uint32_t inputIndex, const Model& model, const bool IsOptional);
 
 ConstTensorPin ConvertOperandToConstTensorPin(const Operand& operand,
                                               const Model& model,
diff --git a/shim/sl/canonical/Converter.cpp b/shim/sl/canonical/Converter.cpp
index 5b09da9..a00a0af 100644
--- a/shim/sl/canonical/Converter.cpp
+++ b/shim/sl/canonical/Converter.cpp
@@ -999,7 +999,7 @@
     // filter's height and width indices to match the input's height and width indices so we permute it to OIHW if
     // the DataLayout is NCHW
 
-    if (!IsWeightsValid(operation, 1, model) && desc.m_DataLayout == DataLayout::NCHW)
+    if (!IsWeightsValid(operation, 1, model, false) && desc.m_DataLayout == DataLayout::NCHW)
     {
         return Fail("%s: Operation has unsupported weights OperandLifeTime", __func__);
     }
@@ -1229,13 +1229,14 @@
     const armnn::TensorInfo& outputInfo = GetTensorInfoForOperand(*output);
 
     // ArmNN does not currently support non-fixed weights or bias
+    if (!IsWeightsValid(operation, 1, model, false))
+    {
+        return Fail("%s: This Operation has unsupported weights OperandLifeTime", __func__);
+    }
+
     // Find the shape of the weights tensor. In AndroidNN this will be [ 1, H, W, I * M ]
     const Operand* weightsOperand = GetInputOperand(operation, 1, model);
 
-    if (!weightsOperand)
-    {
-        return Fail("%s: Could not read weights", __func__);
-    }
     // Basic sanity check on the weights shape.
     // ANEURALNETWORKS_DEPTHWISE_CONV_2D specifies a 4-D tensor, of shape
     // [1, filter_height, filter_width, depth_out]