From 14d6e95df34a90db0fb34c1fe0479d93ebcf951d Mon Sep 17 00:00:00 2001 From: Alexander Bengtsson Date: Thu, 24 Apr 2025 15:03:44 +0200 Subject: [PATCH] MLBEDSW-9758: Fix negative offsets in DecomposeForStrides Fix handling of negative offsets when rejecting slices in stride decomposition. - Treat negative offsets as TOP/LEFT padding. - Adjust coordinate with IfmStride to find first positive coordinate - Determine whether first positive coordinate results in a volume Change-Id: I2ecd5a5547f13f9efbc280339ab0e076bdce67f9 Signed-off-by: Alexander Bengtsson --- ethosu/regor/compiler/scheduler_decompose.cpp | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/ethosu/regor/compiler/scheduler_decompose.cpp b/ethosu/regor/compiler/scheduler_decompose.cpp index 0ce98d1a..51cf2518 100644 --- a/ethosu/regor/compiler/scheduler_decompose.cpp +++ b/ethosu/regor/compiler/scheduler_decompose.cpp @@ -676,7 +676,6 @@ DecomposeForStrides(Architecture *arch, std::unique_ptr op, { for ( auto kx = 0; kx < kernelSize.x; kx++ ) { - auto newIfmSlice = ifmConn->slice; auto ifmStrides = ifmConn->stepXY; newIfmSlice.offset = @@ -695,20 +694,47 @@ DecomposeForStrides(Architecture *arch, std::unique_ptr op, std::min(ifmConn->shape.Width() - newIfmSlice.offset.Width(), newIfmSlice.shape.Width() + extend.x))); ifmStrides.y *= SY; ifmStrides.x *= SX; - auto &padding = kernel->Padding(); // Don't generate an op that will only produce zeros, unless it is the last one in the group, // and we have not sent one before. - if ( (newIfmSlice.offset.Height() < 0 || newIfmSlice.shape.Height() == 0) && - (ky < (kernelSize.y - 1) || kx < (kernelSize.x - 1) || didSendOne) ) - { - auto ifmPointsY = newIfmSlice.shape.Height() / ifmStrides.y; - if ( ifmPointsY <= 0 ) continue; - } - if ( (newIfmSlice.offset.Width() < 0 || newIfmSlice.shape.Width() == 0) && - (ky < (kernelSize.y - 1) || kx < (kernelSize.x - 1) || didSendOne) ) + if ( ky < (kernelSize.y - 1) || kx < (kernelSize.x - 1) || didSendOne ) { - auto ifmPointsX = newIfmSlice.shape.Width() / ifmStrides.x; - if ( ifmPointsX <= 0 ) continue; + // Find if the slice reads elements inside the IFM (not counting the padded-area) + // for a positive offset this is at least one as long as the shape has nonZero volume + if ( newIfmSlice.shape.Elements64() <= 0 ) + { + // zero-volume read-shape + continue; + } + // for a negative offset (which should be interpreted as left/top padding) + // we need to account for ifmStrides and compute the first positive offset + if ( newIfmSlice.offset.Height() < 0 ) + { + // Find first positive coordinate and check whether it is inside the slice + int firstH = (newIfmSlice.offset.Height() % ifmStrides.y); + if ( firstH < 0 ) + { + firstH += ifmStrides.y; + } + if ( firstH >= newIfmSlice.shape.Height() ) + { + // First positive coordinate results in zero volume + continue; + } + } + else if ( newIfmSlice.offset.Width() < 0 ) + { + // Find first positive coordinate results in zero volume + int firstW = (newIfmSlice.offset.Width() % ifmStrides.x); + if ( firstW < 0 ) + { + firstW += ifmStrides.x; + } + if ( firstW >= newIfmSlice.shape.Width() ) + { + // First positive coordinate is outside of the slice-shape + continue; + } + } } Point2i ifmPoints = DivRoundUp((Point2i{newIfmSlice.shape.Width(), newIfmSlice.shape.Height()} + -- GitLab