https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128303
Bug ID: 128303
Summary: [MVE] 16 -> 32-bit widening reductions (dot product,
widening sum) not vectorized for Cortex-M55
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: aleksandr.o.makarov at gmail dot com
Target Milestone: ---
Version: GCC 16.1.0, arm-none-eabi (Compiler Explorer)
Flags: -O3 -mcpu=cortex-m55 -mthumb -mfloat-abi=hard -mfpu=auto
-fopt-info-vec-all
Source code:
```
#include <stdint.h>
int32_t dot16(const int16_t *restrict x, const int16_t *restrict y, int n)
{
int32_t acc = 0;
for (int i = 0; i < n; i++)
acc += (int32_t)x[i] * y[i];
return acc;
}
int32_t sum16(const int16_t *restrict x, int n)
{
int32_t acc = 0;
for (int i = 0; i < n; i++)
acc += x[i];
return acc;
}
/* Control: same-width reduction, which is vectorized. */
int32_t dot32(const int32_t *restrict x, const int32_t *restrict y, int n)
{
int32_t acc = 0;
for (int i = 0; i < n; i++)
acc += x[i] * y[i];
return acc;
}
```
Observed: dot32 is vectorized (vldrw.32, vmul.i32, vadd.i32, vaddv.s32). dot16
and sum16 stay scalar:
dot16: ldrh / ldrh / smlabb / le (one element per iteration)
sum16: ldrsh / add / le
The vectorizer tries V8HI and V8QI and gives up:
missed: couldn't vectorize loop
missed: unsupported SLP instances
note: ***** Analysis failed with vector mode V8HI
note: ***** Analysis failed with vector mode V8QI
Making the trip count a constant (64) doesn't change the result.
Expected: MVE has single-instruction widening reductions: VMLADAVA.S16
(multiply-accumulate across vector into a 32-bit scalar) and VADDVA.S16. Clang
(trunk, --target=thumbv8.1m.main-none-eabi -mcpu=cortex-m55 -O3) compiles dot16
to:
dlstp.16 lr, r2
vldrh.u16 q0, [r0], #16
vldrh.u16 q1, [r1], #16
vmlava.s16 r12, q0, q1
letp lr, ...
This looks like the MVE backend is missing the sdot_prod / widen_ssum (or
equivalent reduction) patterns for V8HI→SI, possibly V16QI too. LLVM needed the
equivalent i8/i16 VMLAV patterns.
Impact: 16-bit fixed-point DSP code (audio codecs such as libopus: pitch
correlation, inner products, LPC filters) gets no MVE benefit from GCC on
Cortex-M55/M85.
Minor, related: even for dot32, GCC emits dls/le plus a scalar epilogue instead
of a tail-predicated dlstp/letp loop.