https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120660
--- Comment #1 from Zdenek Sojka <zsojka at seznam dot cz> ---
The difference between OK and BAD is:
$ diff -u OK.S BAD.S
--- OK.S 2025-07-15 16:39:49.437945918 +0200
+++ BAD.S 2025-07-15 16:39:53.377945956 +0200
@@ -14,7 +14,7 @@
@ GNU C23 (GCC) version 16.0.0 20250714 (experimental)
(armv7a-hardfloat-linux-gnueabi)
@ compiled by GNU C version 14.3.0, GMP version 6.3.0, MPFR version
4.2.2, MPC version 1.3.1, isl version none
@ GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
-@ options passed: -mfloat-abi=hard -mfpu=vfpv4 -mtls-dialect=gnu -marm
-march=armv7-a+vfpv4 -O
+@ options passed: -mfloat-abi=hard -mfpu=vfpv4 -mtls-dialect=gnu -marm
-march=armv7-a+vfpv4 -O -favoid-store-forwarding
.text
.align 2
.global foo
@@ -26,14 +26,14 @@
@ frame_needed = 0, uses_anonymous_args = 0
@ link register save eliminated.
sub sp, sp, #8 @,,
- strh r0, [sp, #6] @ movhi @ s, s
@ testcase.c:6: __builtin_memset (&s, c, 1);
movw r3, #:lower16:.LANCHOR0 @ tmp99,
movt r3, #:upper16:.LANCHOR0 @ tmp99,
ldr r3, [r3] @ c, c
- strb r3, [sp, #6] @ c, MEM <char[1:1]> [(void *)&s]
@ testcase.c:8: }
- ldrsh r0, [sp, #6] @, s
+ strh r0, [sp, #6] @ movhi @ tmp109, s
+ strb r3, [sp, #6] @ tmp108, MEM <char[1:1]> [(void *)&s]
+ sxth r0, r3 @, tmp107
add sp, sp, #8 @,,
@ sp needed @
bx lr @
eg. (r0 = 's', r3 = 'c'), OK:
strh r0, [sp, #6] @ movhi @ s, s
strb r3, [sp, #6] @ c, MEM <char[1:1]> [(void *)&s]
ldrsh r0, [sp, #6] @, s
BAD:
strh r0, [sp, #6] @ movhi @ tmp109, s
strb r3, [sp, #6] @ tmp108, MEM <char[1:1]> [(void *)&s]
sxth r0, r3 @, tmp107
the difference is the last instruction. BAD just sign-extends (16-bit) 'c' to
(32-bit) 's' as return value (zero). OK correctly reads 's' as (16-bit) value
from stack, sign-extended to 32-bit.