Skip to content

fix(none.h): widen SMLALD/SMLALDX products to 64-bit before summing#320

Open
saikumar-mandaji wants to merge 1 commit into
ARM-software:mainfrom
saikumar-mandaji:fix/smlald-32bit-overflow
Open

fix(none.h): widen SMLALD/SMLALDX products to 64-bit before summing#320
saikumar-mandaji wants to merge 1 commit into
ARM-software:mainfrom
saikumar-mandaji:fix/smlald-32bit-overflow

Conversation

@saikumar-mandaji

Copy link
Copy Markdown

Fixes #319

Problem

The software fallback __SMLALD/__SMLALDX in Include/dsp/none.h — used on cores without the hardware DSP extension (Cortex-M0/M0+/M3/M23) — computed both 16x16 products as 32-bit q31_t and summed them before widening to the 64-bit accumulator. Two same-sign near-full-scale products (each up to 2^30) sum to 2^31, overflowing signed 32-bit and wrapping negative before the (q63_t)sum widening ever applies.

This silently produces wrong results in every Q15 function that hits this fallback on a non-DSP core, including arm_fir_q15, arm_mat_vec_mult_q15, arm_lms_q15, arm_lms_norm_q15, arm_conv_opt_q15/arm_conv_partial_opt_q15, and arm_correlate_opt_q15 — directly contradicting the documented guarantee that the 64-bit accumulator carries "no risk of internal overflow."

Minimal repro (from the issue): x = y = 0x80008000 (both 16-bit halves = -32768). Each product is (-32768)*(-32768) = 2^30; their 32-bit sum 2^31 wraps to -2^31 under the old code. The true value is +2^31.

Fix

Cast one operand of each product to q63_t before multiplying, so C's usual arithmetic conversions promote the whole product (and the sum) to 64-bit. Same shape for both __SMLALD and __SMLALDX, matching the fix already suggested in the issue.

Verification

Verified by hand against the issue's worked arithmetic (the minimal-isolation case and the arm_fir_q15 accumulation trace). No C compiler was available in the environment this patch was authored in, so I was not able to run the reproduction or the test suite directly -- please double-check against CI/local build before merging, and let me know if you'd like a test case added.

The software fallback __SMLALD/__SMLALDX in Include/dsp/none.h (used
on cores without the hardware DSP extension, e.g. Cortex-M0/M0+/M3/M23)
computed both 16x16 products as 32-bit q31_t and summed them before
widening to the 64-bit accumulator. Two same-sign near-full-scale
products (each up to 2^30) sum to 2^31, overflowing signed 32-bit and
wrapping negative before the (q63_t)sum widening ever applies.

This silently produces wrong results in every Q15 function that hits
this fallback on a non-DSP core, including arm_fir_q15,
arm_mat_vec_mult_q15, arm_lms_q15, arm_lms_norm_q15,
arm_conv_opt_q15/arm_conv_partial_opt_q15, and
arm_correlate_opt_q15 -- directly contradicting the documented
guarantee that the 64-bit accumulator carries no risk of internal
overflow.

Minimal repro (from the issue): x = y = 0x80008000 (both 16-bit
halves = -32768). Each product is (-32768)*(-32768) = 2^30; their
32-bit sum 2^31 wraps to -2^31 under the old code. The true value is
+2^31.

Fix: cast one operand of each product to q63_t before multiplying, so
C's usual arithmetic conversions promote the whole product (and the
sum) to 64-bit, matching the fix already suggested in the issue.
Verified by hand against the issue's worked arithmetic; no C compiler
was available in the environment this patch was authored in to run
the reproduction directly, so please double check against CI/local
build before merging.

Fixes ARM-software#319

Signed-off-by: Saikumar Mandaji <mandajisaikumar@gmail.com>
@christophe0606

Copy link
Copy Markdown
Contributor

Waiting for some feedback on #319 because although I agree with the fix, I also want to understand in which conditions the problem occurs since I have not been able to reproduce it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

none.h __SMLALD/__SMLALDX: 32-bit intermediate overflow produces wrong Q15 filter results on non-DSP cores (Cortex-M0/M0+/M3/M23)

3 participants