From ffd371503471f804e55b92f815db25c7d48a33c4 Mon Sep 17 00:00:00 2001 From: Philip Hall Date: Thu, 12 Jun 2025 13:05:23 +0100 Subject: [PATCH] MLBEDSW-10891: Fix GraphIR boolean tensor handling An update to elementwise constraint checking highlighted a bug in the handling of GraphIR boolean translation. - This commit ensures that the elementwise boolean operators have compatibly typed inputs. - Updated Ethos-U85 elementwise type tables. - Updated constant tensor creation to avoid temporary vector construction for a single value.. Signed-off-by: Philip Hall Change-Id: I2d4b29a86cdaf1bd62a7e650673087cc1d3fd7bb --- .../ethosu85/ethos_u85_constraints.cpp | 40 ++++++++++--------- ethosu/regor/common/buffer_view.hpp | 3 +- ethosu/regor/common/data_type.hpp | 7 +++- ethosu/regor/compiler/graphir_optimiser.cpp | 4 +- ethosu/regor/compiler/operation_util.hpp | 4 +- 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp index 57bcf353..91fee32c 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp @@ -27,8 +27,11 @@ namespace regor { // Table of allowed ifm/ofm data type combinations for each HWOp -static const std::array s_defaultAllTypes = {DataType::UInt8, DataType::Int8, DataType::Int16, DataType::Int32, DataType::Int64}; -static const std::array s_defaultAllTypesExcl64 = { +static const std::array s_defaultAllTypes = { + DataType::Bool8, DataType::UInt8, DataType::Int8, DataType::Int16, DataType::Int32, DataType::Int64}; +static const std::array s_defaultIntegerTypes = { + DataType::UInt8, DataType::Int8, DataType::Int16, DataType::Int32, DataType::Int64}; +static const std::array s_defaultIntegerTypesExcl64 = { DataType::UInt8, DataType::Int8, DataType::Int16, DataType::Int32, DataType::Int64}; static const std::array s_reduceMinMaxTypes = { DataType::Bool8, DataType::UInt8, DataType::Int8, DataType::Int16, DataType::Int32}; @@ -43,21 +46,21 @@ static const std::array s_defaultInt32_64 = {DataType::Int32, DataT static const std::unordered_map>> s_opDataTypeSupport = { {EthosU85NpuOp::Convolution, { - {DataType::UInt8, s_defaultAllTypes}, - {DataType::Int8, s_defaultAllTypes}, - {DataType::Int16, s_defaultAllTypes}, + {DataType::UInt8, s_defaultIntegerTypes}, + {DataType::Int8, s_defaultIntegerTypes}, + {DataType::Int16, s_defaultIntegerTypes}, }}, {EthosU85NpuOp::Depthwise, { - {DataType::UInt8, s_defaultAllTypes}, - {DataType::Int8, s_defaultAllTypes}, - {DataType::Int16, s_defaultAllTypes}, + {DataType::UInt8, s_defaultIntegerTypes}, + {DataType::Int8, s_defaultIntegerTypes}, + {DataType::Int16, s_defaultIntegerTypes}, }}, {EthosU85NpuOp::VectorProduct, { - {DataType::UInt8, s_defaultAllTypes}, - {DataType::Int8, s_defaultAllTypes}, - {DataType::Int16, s_defaultAllTypes}, + {DataType::UInt8, s_defaultIntegerTypes}, + {DataType::Int8, s_defaultIntegerTypes}, + {DataType::Int16, s_defaultIntegerTypes}, }}, {EthosU85NpuOp::Pooling, { @@ -76,10 +79,10 @@ static const std::unordered_map ifmTypes = s_defaultAllTypes; ofmTypes = s_defaultAllTypes; diff --git a/ethosu/regor/common/buffer_view.hpp b/ethosu/regor/common/buffer_view.hpp index 8353757e..b7ec922b 100644 --- a/ethosu/regor/common/buffer_view.hpp +++ b/ethosu/regor/common/buffer_view.hpp @@ -136,10 +136,9 @@ public: Buffer(const ConstValue &value) : _typeHash(TypeHash::value), _utypeHash(TypeHash>::value) { - _refData.constValue = uint64_t(value._value); + _refData.constValue = uint64_t(std::make_unsigned_t(value._value)); _sizeBytes = sizeof(TYPE); _placement = Placement::LocalConst; - _dataHash.v32[0] = uint32_t(value._value); } template::value, int> = 0> diff --git a/ethosu/regor/common/data_type.hpp b/ethosu/regor/common/data_type.hpp index 4d7b1f0a..2d2f9a12 100644 --- a/ethosu/regor/common/data_type.hpp +++ b/ethosu/regor/common/data_type.hpp @@ -1,5 +1,5 @@ // -// SPDX-FileCopyrightText: Copyright 2021-2024 Arm Limited and/or its affiliates +// SPDX-FileCopyrightText: Copyright 2021-2025 Arm Limited and/or its affiliates // // SPDX-License-Identifier: Apache-2.0 // @@ -273,6 +273,11 @@ struct DataTypeOf static constexpr DataType value = DataType::None; }; template<> +struct DataTypeOf +{ + static constexpr DataType value = DataType::Bool8; +}; +template<> struct DataTypeOf { static constexpr DataType value = DataType::Int8; diff --git a/ethosu/regor/compiler/graphir_optimiser.cpp b/ethosu/regor/compiler/graphir_optimiser.cpp index ca73a848..21326689 100644 --- a/ethosu/regor/compiler/graphir_optimiser.cpp +++ b/ethosu/regor/compiler/graphir_optimiser.cpp @@ -89,7 +89,7 @@ Tensor *GraphIrOptimiser::ConvertBool8Tensors(Graph *graph, Tensor *tensor) // Create and insert an elementwise CMP_NE to convert to internal bool representation auto newOp = std::make_shared(OpType::NotEqual); newOp->ConnectInput(TensorUsage::IFM0, graphInputTensor); - newOp->ConnectInput(TensorUsage::IFM1, CreateConstTensor("const_zero", int8_t(0))); + newOp->ConnectInput(TensorUsage::IFM1, CreateConstTensor("const_zero", bool(false))); newOp->ConnectOutput(TensorUsage::OFM, newTensor); RecordOptimisation(graph, newOp.get()); returnTensor = graphInputTensor.get(); @@ -105,7 +105,7 @@ Tensor *GraphIrOptimiser::ConvertBool8Tensors(Graph *graph, Tensor *tensor) // Create and insert an elementwise BITWISE_AND to convert from internal bool representation auto newOp = std::make_shared(OpType::And); newOp->ConnectInput(TensorUsage::IFM0, newTensor); - newOp->ConnectInput(TensorUsage::IFM1, CreateConstTensor("const_one", int8_t(1))); + newOp->ConnectInput(TensorUsage::IFM1, CreateConstTensor("const_one", bool(true))); newOp->ConnectOutput(TensorUsage::OFM, graphOutputTensor); RecordOptimisation(graph, newOp.get()); returnTensor = newTensor.get(); diff --git a/ethosu/regor/compiler/operation_util.hpp b/ethosu/regor/compiler/operation_util.hpp index f58bacee..a52640ef 100644 --- a/ethosu/regor/compiler/operation_util.hpp +++ b/ethosu/regor/compiler/operation_util.hpp @@ -59,8 +59,8 @@ inline std::shared_ptr CreateConstTensor( template std::shared_ptr CreateConstTensor(const std::string &name, T value) { - auto buf = std::make_shared(std::vector{value}); - return CreateConstTensor(name, DataTypeOf::value, buf); + using T2 = typename std::conditional::value, uint8_t, T>::type; + return CreateConstTensor(name, DataTypeOf::value, std::make_shared(Buffer::ConstValue(T2(value)))); } // Create a single element constant tensor with the specified data type and value (value is not bounds-checked) -- GitLab