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.