diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp index 338a65b32b001593c47f2ea4bdef648365933b0b..535ede5ca4e0390d4d75603a34a3fe4b125ff5cb 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_constraints.cpp @@ -130,7 +130,9 @@ bool EthosU85Constraints::SupportsFusedRescale(OpType opType, TensorUsage tensor else if ( npuOp == EthosU85NpuOp::Resize && globalScale ) { auto &qs = quantization.scales.front(); - return qs.scale == 1 && qs.shift >= 16; // Only shift of 16 or more supported + // Only shift < 48 supported + const auto normalized = QuantizedScale::ReduceScale(qs); + return normalized.scale == 1 && normalized.shift < 48; } else if ( npuOp == EthosU85NpuOp::Elementwise && globalScale ) { diff --git a/ethosu/regor/architecture/ethosu85/ethos_u85_register_cs_generator.cpp b/ethosu/regor/architecture/ethosu85/ethos_u85_register_cs_generator.cpp index 066d4bb2825ef40ec4bb143941de4f47ae8fb268..6a41e69ec4be6afab4b8bd6bd89968c0eb41cc45 100644 --- a/ethosu/regor/architecture/ethosu85/ethos_u85_register_cs_generator.cpp +++ b/ethosu/regor/architecture/ethosu85/ethos_u85_register_cs_generator.cpp @@ -1906,8 +1906,9 @@ void EthosU85RCSGenerator::GenerateResizeOp(HLCStripe *stripe, MemoryAccesses &m // calculate ifm width read int ifmWidthRead = ((ofmShape.Width() - 1) * scale_w.d + offset_w) / scale_w.n + 2; - // scaling is shift only and + 16 - QuantizedScale ofmScale = op->ofm.quantization.scales[0]; + // scaling is shift only and + 16, so convert to scale 1 and add 16 + const QuantizedScale ofmScale = QuantizedScale::ReduceScale(op->ofm.quantization.scales.front()); + assert(ofmScale.scale == 1); int shift = 16 + ofmScale.shift; // X - width diff --git a/ethosu/regor/common/scaling.cpp b/ethosu/regor/common/scaling.cpp index 1032a10267d16ad86a3d69516122bea6e229b68c..1e5d4d0f0da6c4f363ecda5097eaedb789752d4b 100644 --- a/ethosu/regor/common/scaling.cpp +++ b/ethosu/regor/common/scaling.cpp @@ -81,6 +81,18 @@ const QuantizedScale &QuantizedScale::Unit() return unitScale; } +QuantizedScale QuantizedScale::ReduceScale(const QuantizedScale &qs) +{ + auto scale = qs.scale; + auto shift = qs.shift; + while ( scale > 1 && (scale & 0x1) == 0 && shift > 0 ) + { + scale >>= 1; + shift--; + } + return {scale, shift}; +} + // Convert int32_t multiplier to int16_t with rounding. int16_t DownScaleInt32ToInt16Multiplier(int32_t multiplier) { diff --git a/ethosu/regor/common/scaling.hpp b/ethosu/regor/common/scaling.hpp index 54fd722936a6f7c080b75562874a14a20b29564c..0b4d0360af3209bb9fb76809abf24ae717c5e026 100644 --- a/ethosu/regor/common/scaling.hpp +++ b/ethosu/regor/common/scaling.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 // @@ -46,6 +46,7 @@ public: * Unit scale, i.e. no scaling */ static const QuantizedScale &Unit(); + static QuantizedScale ReduceScale(const QuantizedScale &qs); }; /* Calculate elementwise Mul OFM QuantizedScale */ diff --git a/ethosu/regor/compiler/graphir_optimiser.cpp b/ethosu/regor/compiler/graphir_optimiser.cpp index 644b55be1ab27fc512e17b6c80ee51a7c798af2f..7d0c68d8f133b06ee76e80862deb0618c416d934 100644 --- a/ethosu/regor/compiler/graphir_optimiser.cpp +++ b/ethosu/regor/compiler/graphir_optimiser.cpp @@ -901,7 +901,7 @@ Operation *GraphIrOptimiser::FuseRescale(Graph *const graph, Operation *const op { if ( qs.shift > 0 && qs.shift < 31 && (qs.scale % (1 << qs.shift)) == 0 ) { - qs = {(qs.scale >> qs.shift), 0}; + qs = QuantizedScale::ReduceScale(qs); } } return scales;