On Mon, 24 Aug 2026, Konstantinos Eleftheriou wrote:
> From: Philipp Tomsich <[email protected]>
>
> synth_mult accepts a sub-algorithm of up to MAX_BITS_PER_WORD
> operations from its recursive call and appends the current operation
> at index ops before the too-long check discards the result. That
> index is one past both arrays. The write to op[MAX_BITS_PER_WORD]
> aliases log[0..3] and overwrites the shift counts of the algorithm
> being built, and the write to log[MAX_BITS_PER_WORD] falls outside
> the struct. The cache update just above the check reads op[] at the
> same index.
>
> AVR reaches this at -O1/-O2, where MAX_BITS_PER_WORD is 8 and a
> SImode multiply by a dense constant needs more operations than that:
>
> uint32_t f (uint32_t x) { return x * 0xaaab; }
>
> Size the arrays for the transient state.
OK.
> PR middle-end/127031
>
> gcc/ChangeLog:
>
> * expmed.h (struct algorithm): Add one slot to the op and log
> arrays for the operation synth_mult appends to a full
> sub-algorithm before discarding it.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/avr/pr127031.c: New test.
> ---
> gcc/expmed.h | 9 ++++++---
> gcc/testsuite/gcc.target/avr/pr127031.c | 9 +++++++++
> 2 files changed, 15 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/gcc.target/avr/pr127031.c
>
> diff --git a/gcc/expmed.h b/gcc/expmed.h
> index 78f3f36e6615..4a2c60e055e5 100644
> --- a/gcc/expmed.h
> +++ b/gcc/expmed.h
> @@ -101,9 +101,12 @@ struct algorithm
> word size, but the worst-case algorithms will be if we have few
> consecutive ones or zeros, i.e., a multiplicand like 10101010101...
> In that case we will generate shift-by-2, add, shift-by-2, add,...,
> - in total wordsize operations. */
> - enum alg_code op[MAX_BITS_PER_WORD];
> - char log[MAX_BITS_PER_WORD];
> + in total wordsize operations. OPS never exceeds MAX_BITS_PER_WORD,
> + and the final entry is scratch: the algorithm search appends an
> + operation there before checking whether the sequence has grown too
> + long. */
> + enum alg_code op[MAX_BITS_PER_WORD + 1];
> + char log[MAX_BITS_PER_WORD + 1];
> };
>
> /* The entry for our multiplication cache/hash table. */
> diff --git a/gcc/testsuite/gcc.target/avr/pr127031.c
> b/gcc/testsuite/gcc.target/avr/pr127031.c
> new file mode 100644
> index 000000000000..12d978af17eb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/avr/pr127031.c
> @@ -0,0 +1,9 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +
> +typedef __UINT32_TYPE__ uint32_t;
> +
> +uint32_t f (uint32_t x)
> +{
> + return x * 0xaaab;
> +}
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)